Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Supervisor
- Optimization enabled
- true
- Compiler version
- v0.8.2+commit.661d1103
- Optimization runs
- 200
- EVM Version
- istanbul
- Verified at
- 2024-07-02T12:17:07.029457Z
Constructor Arguments
000000000000000000000000000000000000000000000000000000000000290b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000517beb62d45e7637a2db115679f36936bdbb05d2000000000000000000000000207d2d9c74f4c8acdfcb5765d7dccc92e2861094
Supervisor.sol
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.2; import "ECDSA.sol"; /// @title Supervisor is the guardian of YPool. It requires multiple validators to valid /// the requests from users and workers and sign on them if valid. contract Supervisor { using ECDSA for bytes32; /* ========== STATE VARIABLES ========== */ bytes32 public constant SET_THRESHOLD_IDENTIFIER = 'SET_THRESHOLD'; bytes32 public constant SET_VALIDATOR_IDENTIFIER = 'SET_VALIDATOR'; bytes32 public constant VALIDATE_XY_CROSS_CHAIN_IDENTIFIER = 'VALIDATE_XY_XCHAIN_IDENTIFIER'; // the chain ID contract located at uint32 immutable public chainId; // number of validators uint256 public validatorsNum; // threshold to pass the signature validation uint256 public threshold; // current nonce for write functions uint256 public nonce; // check if the address is one of the validators mapping (address => bool) public validators; /// @dev Constuctor with chainId / validators / threshold /// @param _chainId The chain ID located with /// @param _validators Initial validator addresses /// @param _threshold Initial threshold to pass the request validation constructor(uint32 _chainId, address [] memory _validators, uint256 _threshold) { chainId = _chainId; for (uint256 i; i < _validators.length; i++) { validators[_validators[i]] = true; } validatorsNum = _validators.length; require(_threshold <= validatorsNum, "ERR_INVALID_THRESHOLD"); threshold = _threshold; } /* ========== VIEW FUNCTIONS ========== */ /// @notice Check if there are enough signed signatures to the signature hash /// @param sigIdHash The signature hash to be signed /// @param signatures Signed signatures by different validators function checkSignatures(bytes32 sigIdHash, bytes[] memory signatures) public view { require(signatures.length >= threshold, "ERR_NOT_ENOUGH_SIGNATURES"); address prevAddress = address(0); for (uint i; i < threshold; i++) { address recovered = sigIdHash.recover(signatures[i]); require(validators[recovered], "ERR_NOT_VALIDATOR"); require(recovered > prevAddress, "ERR_WRONG_SIGNER_ORDER"); prevAddress = recovered; } } /* ========== WRITE FUNCTIONS ========== */ /// @notice Change `threshold` by providing a correct nonce and enough signatures from validators /// @param _threshold New `threshold` /// @param _nonce The nonce to be processed /// @param signatures Signed signatures by validators function setThreshold(uint256 _threshold, uint256 _nonce, bytes[] memory signatures) external { require(signatures.length >= threshold, "ERR_NOT_ENOUGH_SIGNATURES"); require(_nonce == nonce, "ERR_INVALID_NONCE"); require(_threshold > 0, "ERR_INVALID_THRESHOLD"); require(_threshold <= validatorsNum, "ERR_INVALID_THRESHOLD"); bytes32 sigId = keccak256(abi.encodePacked(SET_THRESHOLD_IDENTIFIER, address(this), chainId, _threshold, _nonce)); bytes32 sigIdHash = sigId.toEthSignedMessageHash(); checkSignatures(sigIdHash, signatures); threshold = _threshold; nonce++; } /// @notice Set / remove the validator address to be part of signatures committee /// @param _validator The address to add or remove /// @param flag `true` to add, `false` to remove /// @param _nonce The nonce to be processed /// @param signatures Signed signatures by validators function setValidator(address _validator, bool flag, uint256 _nonce, bytes[] memory signatures) external { require(_validator != address(0), "ERR_INVALID_VALIDATOR"); require(signatures.length >= threshold, "ERR_NOT_ENOUGH_SIGNATURES"); require(_nonce == nonce, "ERR_INVALID_NONCE"); require(flag != validators[_validator], "ERR_OPERATION_TO_VALIDATOR"); bytes32 sigId = keccak256(abi.encodePacked(SET_VALIDATOR_IDENTIFIER, address(this), chainId, _validator, flag, _nonce)); bytes32 sigIdHash = sigId.toEthSignedMessageHash(); checkSignatures(sigIdHash, signatures); if (validators[_validator]) { validatorsNum--; validators[_validator] = false; if (validatorsNum < threshold) threshold--; } else { validatorsNum++; validators[_validator] = true; } nonce++; } }
ECDSA.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return tryRecover(hash, r, vs); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s; uint8 v; assembly { s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) v := add(shr(255, vs), 27) } return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{"Supervisor.sol":{}},"evmVersion":"istanbul"}
Contract ABI
[{"type":"constructor","inputs":[{"type":"uint32","name":"_chainId","internalType":"uint32"},{"type":"address[]","name":"_validators","internalType":"address[]"},{"type":"uint256","name":"_threshold","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"SET_THRESHOLD_IDENTIFIER","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"SET_VALIDATOR_IDENTIFIER","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"VALIDATE_XY_CROSS_CHAIN_IDENTIFIER","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"chainId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkSignatures","inputs":[{"type":"bytes32","name":"sigIdHash","internalType":"bytes32"},{"type":"bytes[]","name":"signatures","internalType":"bytes[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nonce","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setThreshold","inputs":[{"type":"uint256","name":"_threshold","internalType":"uint256"},{"type":"uint256","name":"_nonce","internalType":"uint256"},{"type":"bytes[]","name":"signatures","internalType":"bytes[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setValidator","inputs":[{"type":"address","name":"_validator","internalType":"address"},{"type":"bool","name":"flag","internalType":"bool"},{"type":"uint256","name":"_nonce","internalType":"uint256"},{"type":"bytes[]","name":"signatures","internalType":"bytes[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"threshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"validators","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"validatorsNum","inputs":[]}]
Contract Creation Code
0x60a06040523480156200001157600080fd5b506040516200114b3803806200114b833981016040819052620000349162000146565b6001600160e01b031960e084901b1660805260005b8251811015620000c1576001600360008584815181106200007a57634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000b88162000242565b91505062000049565b50815160008190558111156200011d5760405162461bcd60e51b815260206004820152601560248201527f4552525f494e56414c49445f5448524553484f4c440000000000000000000000604482015260640160405180910390fd5b60015550620002809050565b80516001600160a01b03811681146200014157600080fd5b919050565b6000806000606084860312156200015b578283fd5b835163ffffffff811681146200016f578384fd5b602085810151919450906001600160401b03808211156200018e578485fd5b818701915087601f830112620001a2578485fd5b815181811115620001b757620001b76200026a565b838102604051601f19603f83011681018181108582111715620001de57620001de6200026a565b604052828152858101935084860182860187018c1015620001fd578889fd5b8895505b838610156200022a57620002158162000129565b85526001959095019493860193860162000201565b50809750505050505050604084015190509250925092565b60006000198214156200026357634e487b7160e01b81526011600452602481fd5b5060010190565b634e487b7160e01b600052604160045260246000fd5b60805160e01c610e9e620002ad600039600081816101550152818161045d01526106510152610e9e6000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c806371aca57e1161007157806371aca57e14610116578063935d91dd1461013d5780639a8a059214610150578063affed0e01461018c578063da8bd3fe14610195578063fa52c7d8146101a8576100a9565b80633c0e39bf146100ae57806342cde4e8146100d85780634f9c36b4146100e157806351f61efa146100ea5780635a0f883014610101575b600080fd5b6100c56c14d15517d512149154d213d311609a1b81565b6040519081526020015b60405180910390f35b6100c560015481565b6100c560005481565b6100c56c29a2aa2fab20a624a220aa27a960991b81565b61011461010f366004610d0f565b6101db565b005b6100c57f56414c49444154455f58595f58434841494e5f4944454e54494649455200000081565b61011461014b366004610d54565b610324565b6101777f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020016100cf565b6100c560025481565b6101146101a3366004610ca3565b6104e9565b6101cb6101b6366004610c82565b60036020526000908152604090205460ff1681565b60405190151581526020016100cf565b600154815110156102075760405162461bcd60e51b81526004016101fe90610da2565b60405180910390fd5b6000805b60015481101561031e57600061025184838151811061023a57634e487b7160e01b600052603260045260246000fd5b60200260200101518661079390919063ffffffff16565b6001600160a01b03811660009081526003602052604090205490915060ff166102b05760405162461bcd60e51b815260206004820152601160248201527022a9292fa727aa2fab20a624a220aa27a960791b60448201526064016101fe565b826001600160a01b0316816001600160a01b03161161030a5760405162461bcd60e51b815260206004820152601660248201527522a9292faba927a723afa9a4a3a722a92fa7a92222a960511b60448201526064016101fe565b91508061031681610e21565b91505061020b565b50505050565b600154815110156103475760405162461bcd60e51b81526004016101fe90610da2565b600254821461038c5760405162461bcd60e51b81526020600482015260116024820152704552525f494e56414c49445f4e4f4e434560781b60448201526064016101fe565b600083116103d45760405162461bcd60e51b815260206004820152601560248201527411549497d253959053125117d512149154d213d311605a1b60448201526064016101fe565b60005483111561041e5760405162461bcd60e51b815260206004820152601560248201527411549497d253959053125117d512149154d213d311605a1b60448201526064016101fe565b604080516c14d15517d512149154d213d311609a1b60208201526bffffffffffffffffffffffff193060601b16918101919091526001600160e01b03197f000000000000000000000000000000000000000000000000000000000000000060e01b166054820152605881018490526078810183905260009060980160405160208183030381529060405280519060200120905060006104bc826107b7565b90506104c881846101db565b6001859055600280549060006104dd83610e21565b91905055505050505050565b6001600160a01b0384166105375760405162461bcd60e51b815260206004820152601560248201527422a9292fa4a72b20a624a22fab20a624a220aa27a960591b60448201526064016101fe565b6001548151101561055a5760405162461bcd60e51b81526004016101fe90610da2565b600254821461059f5760405162461bcd60e51b81526020600482015260116024820152704552525f494e56414c49445f4e4f4e434560781b60448201526064016101fe565b6001600160a01b03841660009081526003602052604090205460ff161515831515141561060e5760405162461bcd60e51b815260206004820152601a60248201527f4552525f4f5045524154494f4e5f544f5f56414c494441544f5200000000000060448201526064016101fe565b604080516c29a2aa2fab20a624a220aa27a960991b6020808301919091526bffffffffffffffffffffffff1930606090811b8216848601526001600160e01b03197f000000000000000000000000000000000000000000000000000000000000000060e01b16605485015288901b16605883015285151560f81b606c830152606d80830186905283518084039091018152608d909201909252805191012060006106b7826107b7565b90506106c381846101db565b6001600160a01b03861660009081526003602052604090205460ff161561073e576000805490806106f383610e0a565b90915550506001600160a01b0386166000908152600360205260408120805460ff1916905560015490541015610739576001805490600061073383610e0a565b91905055505b610776565b60008054908061074d83610e21565b90915550506001600160a01b0386166000908152600360205260409020805460ff191660011790555b6002805490600061078683610e21565b9190505550505050505050565b60008060006107a2858561080b565b915091506107af8161087b565b509392505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c016040516020818303038152906040528051906020012090505b919050565b6000808251604114156108425760208301516040840151606085015160001a61083687828585610a81565b94509450505050610874565b82516040141561086c5760208301516040840151610861868383610b6e565b935093505050610874565b506000905060025b9250929050565b600081600481111561089d57634e487b7160e01b600052602160045260246000fd5b14156108a857610a7e565b60018160048111156108ca57634e487b7160e01b600052602160045260246000fd5b14156109185760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016101fe565b600281600481111561093a57634e487b7160e01b600052602160045260246000fd5b14156109885760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016101fe565b60038160048111156109aa57634e487b7160e01b600052602160045260246000fd5b1415610a035760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016101fe565b6004816004811115610a2557634e487b7160e01b600052602160045260246000fd5b1415610a7e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016101fe565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610ab85750600090506003610b65565b8460ff16601b14158015610ad057508460ff16601c14155b15610ae15750600090506004610b65565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015610b35573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610b5e57600060019250925050610b65565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b01610b8f87828885610a81565b935093505050935093915050565b80356001600160a01b038116811461080657600080fd5b6000601f8381840112610bc5578182fd5b8235602067ffffffffffffffff80831115610be257610be2610e52565b610bef8283850201610dd9565b83815282810190878401875b86811015610c735781358a018b603f820112610c1557898afd5b86810135604087821115610c2b57610c2b610e52565b610c3c828c01601f19168a01610dd9565b8281528e82848601011115610c4f578c8dfd5b828285018b83013791820189018c9052508552509285019290850190600101610bfb565b50909998505050505050505050565b600060208284031215610c93578081fd5b610c9c82610b9d565b9392505050565b60008060008060808587031215610cb8578283fd5b610cc185610b9d565b935060208501358015158114610cd5578384fd5b925060408501359150606085013567ffffffffffffffff811115610cf7578182fd5b610d0387828801610bb4565b91505092959194509250565b60008060408385031215610d21578182fd5b82359150602083013567ffffffffffffffff811115610d3e578182fd5b610d4a85828601610bb4565b9150509250929050565b600080600060608486031215610d68578283fd5b8335925060208401359150604084013567ffffffffffffffff811115610d8c578182fd5b610d9886828701610bb4565b9150509250925092565b60208082526019908201527f4552525f4e4f545f454e4f5547485f5349474e41545552455300000000000000604082015260600190565b604051601f8201601f1916810167ffffffffffffffff81118282101715610e0257610e02610e52565b604052919050565b600081610e1957610e19610e3c565b506000190190565b6000600019821415610e3557610e35610e3c565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220807a01d045d9d25157eb6cac5454038894c5b54450502d0c3c8d1f4be4fa5db664736f6c63430008020033000000000000000000000000000000000000000000000000000000000000290b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000517beb62d45e7637a2db115679f36936bdbb05d2000000000000000000000000207d2d9c74f4c8acdfcb5765d7dccc92e2861094
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100a95760003560e01c806371aca57e1161007157806371aca57e14610116578063935d91dd1461013d5780639a8a059214610150578063affed0e01461018c578063da8bd3fe14610195578063fa52c7d8146101a8576100a9565b80633c0e39bf146100ae57806342cde4e8146100d85780634f9c36b4146100e157806351f61efa146100ea5780635a0f883014610101575b600080fd5b6100c56c14d15517d512149154d213d311609a1b81565b6040519081526020015b60405180910390f35b6100c560015481565b6100c560005481565b6100c56c29a2aa2fab20a624a220aa27a960991b81565b61011461010f366004610d0f565b6101db565b005b6100c57f56414c49444154455f58595f58434841494e5f4944454e54494649455200000081565b61011461014b366004610d54565b610324565b6101777f000000000000000000000000000000000000000000000000000000000000290b81565b60405163ffffffff90911681526020016100cf565b6100c560025481565b6101146101a3366004610ca3565b6104e9565b6101cb6101b6366004610c82565b60036020526000908152604090205460ff1681565b60405190151581526020016100cf565b600154815110156102075760405162461bcd60e51b81526004016101fe90610da2565b60405180910390fd5b6000805b60015481101561031e57600061025184838151811061023a57634e487b7160e01b600052603260045260246000fd5b60200260200101518661079390919063ffffffff16565b6001600160a01b03811660009081526003602052604090205490915060ff166102b05760405162461bcd60e51b815260206004820152601160248201527022a9292fa727aa2fab20a624a220aa27a960791b60448201526064016101fe565b826001600160a01b0316816001600160a01b03161161030a5760405162461bcd60e51b815260206004820152601660248201527522a9292faba927a723afa9a4a3a722a92fa7a92222a960511b60448201526064016101fe565b91508061031681610e21565b91505061020b565b50505050565b600154815110156103475760405162461bcd60e51b81526004016101fe90610da2565b600254821461038c5760405162461bcd60e51b81526020600482015260116024820152704552525f494e56414c49445f4e4f4e434560781b60448201526064016101fe565b600083116103d45760405162461bcd60e51b815260206004820152601560248201527411549497d253959053125117d512149154d213d311605a1b60448201526064016101fe565b60005483111561041e5760405162461bcd60e51b815260206004820152601560248201527411549497d253959053125117d512149154d213d311605a1b60448201526064016101fe565b604080516c14d15517d512149154d213d311609a1b60208201526bffffffffffffffffffffffff193060601b16918101919091526001600160e01b03197f000000000000000000000000000000000000000000000000000000000000290b60e01b166054820152605881018490526078810183905260009060980160405160208183030381529060405280519060200120905060006104bc826107b7565b90506104c881846101db565b6001859055600280549060006104dd83610e21565b91905055505050505050565b6001600160a01b0384166105375760405162461bcd60e51b815260206004820152601560248201527422a9292fa4a72b20a624a22fab20a624a220aa27a960591b60448201526064016101fe565b6001548151101561055a5760405162461bcd60e51b81526004016101fe90610da2565b600254821461059f5760405162461bcd60e51b81526020600482015260116024820152704552525f494e56414c49445f4e4f4e434560781b60448201526064016101fe565b6001600160a01b03841660009081526003602052604090205460ff161515831515141561060e5760405162461bcd60e51b815260206004820152601a60248201527f4552525f4f5045524154494f4e5f544f5f56414c494441544f5200000000000060448201526064016101fe565b604080516c29a2aa2fab20a624a220aa27a960991b6020808301919091526bffffffffffffffffffffffff1930606090811b8216848601526001600160e01b03197f000000000000000000000000000000000000000000000000000000000000290b60e01b16605485015288901b16605883015285151560f81b606c830152606d80830186905283518084039091018152608d909201909252805191012060006106b7826107b7565b90506106c381846101db565b6001600160a01b03861660009081526003602052604090205460ff161561073e576000805490806106f383610e0a565b90915550506001600160a01b0386166000908152600360205260408120805460ff1916905560015490541015610739576001805490600061073383610e0a565b91905055505b610776565b60008054908061074d83610e21565b90915550506001600160a01b0386166000908152600360205260409020805460ff191660011790555b6002805490600061078683610e21565b9190505550505050505050565b60008060006107a2858561080b565b915091506107af8161087b565b509392505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c016040516020818303038152906040528051906020012090505b919050565b6000808251604114156108425760208301516040840151606085015160001a61083687828585610a81565b94509450505050610874565b82516040141561086c5760208301516040840151610861868383610b6e565b935093505050610874565b506000905060025b9250929050565b600081600481111561089d57634e487b7160e01b600052602160045260246000fd5b14156108a857610a7e565b60018160048111156108ca57634e487b7160e01b600052602160045260246000fd5b14156109185760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016101fe565b600281600481111561093a57634e487b7160e01b600052602160045260246000fd5b14156109885760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016101fe565b60038160048111156109aa57634e487b7160e01b600052602160045260246000fd5b1415610a035760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016101fe565b6004816004811115610a2557634e487b7160e01b600052602160045260246000fd5b1415610a7e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016101fe565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610ab85750600090506003610b65565b8460ff16601b14158015610ad057508460ff16601c14155b15610ae15750600090506004610b65565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015610b35573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610b5e57600060019250925050610b65565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b01610b8f87828885610a81565b935093505050935093915050565b80356001600160a01b038116811461080657600080fd5b6000601f8381840112610bc5578182fd5b8235602067ffffffffffffffff80831115610be257610be2610e52565b610bef8283850201610dd9565b83815282810190878401875b86811015610c735781358a018b603f820112610c1557898afd5b86810135604087821115610c2b57610c2b610e52565b610c3c828c01601f19168a01610dd9565b8281528e82848601011115610c4f578c8dfd5b828285018b83013791820189018c9052508552509285019290850190600101610bfb565b50909998505050505050505050565b600060208284031215610c93578081fd5b610c9c82610b9d565b9392505050565b60008060008060808587031215610cb8578283fd5b610cc185610b9d565b935060208501358015158114610cd5578384fd5b925060408501359150606085013567ffffffffffffffff811115610cf7578182fd5b610d0387828801610bb4565b91505092959194509250565b60008060408385031215610d21578182fd5b82359150602083013567ffffffffffffffff811115610d3e578182fd5b610d4a85828601610bb4565b9150509250929050565b600080600060608486031215610d68578283fd5b8335925060208401359150604084013567ffffffffffffffff811115610d8c578182fd5b610d9886828701610bb4565b9150509250925092565b60208082526019908201527f4552525f4e4f545f454e4f5547485f5349474e41545552455300000000000000604082015260600190565b604051601f8201601f1916810167ffffffffffffffff81118282101715610e0257610e02610e52565b604052919050565b600081610e1957610e19610e3c565b506000190190565b6000600019821415610e3557610e35610e3c565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220807a01d045d9d25157eb6cac5454038894c5b54450502d0c3c8d1f4be4fa5db664736f6c63430008020033