Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- LayerswapV8
- Optimization enabled
- true
- Compiler version
- v0.8.23+commit.f704f362
- Optimization runs
- 200
- EVM Version
- paris
- Verified at
- 2024-08-30T15:31:27.245424Z
contracts/HashedTimeLockEther.sol
/* _ __ _____ | | __ _ _ _ ___ _ __ _____ ____ _ _ __ \ \ / ( _ ) | | / _` | | | |/ _ \ '__/ __\ \ /\ / / _` | '_ \ \ \ / // _ \ | |__| (_| | |_| | __/ | \__ \\ V V / (_| | |_) | \ V /| (_) | |_____\__,_|\__, |\___|_| |___/ \_/\_/ \__,_| .__/ \_/ \___/ |___/ |_| */ // SPDX-License-Identifier: MIT pragma solidity 0.8.23; import '@openzeppelin/contracts/utils/cryptography/ECDSA.sol'; import '@openzeppelin/contracts/utils/Address.sol'; struct EIP712Domain { string name; string version; uint256 chainId; address verifyingContract; bytes32 salt; } interface IMessenger { function notify( bytes32 commitId, bytes32 hashlock, string memory dstChain, string memory dstAsset, string memory dstAddress, string memory srcAsset, address payable sender, address payable srcReceiver, uint256 amount, uint256 timelock, address tokenContract ) external; } contract LayerswapV8 { using ECDSA for bytes32; using Address for address; bytes32 private DOMAIN_SEPARATOR; bytes32 private constant SALT = keccak256(abi.encodePacked('Layerswap V8')); constructor() { DOMAIN_SEPARATOR = hashDomain( EIP712Domain({ name: 'LayerswapV8', version: '1', chainId: block.chainid, verifyingContract: address(this), salt: SALT }) ); } error FundsNotSent(); error NotFutureTimelock(); error NotPassedTimelock(); error LockAlreadyExists(); error CommitIdAlreadyExists(); error LockNotExists(); error HashlockNotMatch(); error AlreadyRedeemed(); error AlreadyUnlocked(); error NoMessenger(); error CommitmentNotExists(); error AlreadyLocked(); error AlreadyUncommitted(); error NoAllowance(); error InvalidSigniture(); struct HTLC { string dstAddress; string dstChain; string dstAsset; string srcAsset; address payable sender; address payable srcReceiver; bytes32 hashlock; uint256 secret; uint256 amount; uint256 timelock; bool redeemed; bool unlocked; } struct PHTLC { string dstAddress; string dstChain; string dstAsset; string srcAsset; address payable sender; address payable srcReceiver; bytes32 lockId; uint timelock; uint amount; address messenger; bool locked; bool uncommitted; } struct lockCommitmentMsg { bytes32 hashlock; uint256 timelock; } event TokenCommitted( bytes32 commitId, string[] hopChains, string[] hopAssets, string[] hopAddresses, string dstChain, string dstAddress, string dstAsset, address sender, address srcReceiver, string srcAsset, uint amount, uint timelock, address messenger ); event TokenLocked( bytes32 indexed hashlock, string dstChain, string dstAddress, string dstAsset, address indexed sender, address indexed srcReceiver, string srcAsset, uint amount, uint timelock, address messenger, bytes32 commitId ); event LowLevelErrorOccurred(bytes lowLevelData); event TokenUnlocked(bytes32 indexed lockId); event TokenUncommitted(bytes32 indexed commitId); event TokenRedeemed(bytes32 indexed lockId, address redeemAddress); modifier _committed(bytes32 commitId) { if (!hasPHTLC(commitId)) revert CommitmentNotExists(); _; } modifier _locked(bytes32 lockId) { if (!hasHTLC(lockId)) revert LockNotExists(); _; } mapping(bytes32 => HTLC) locks; mapping(bytes32 => PHTLC) commits; mapping(bytes32 => bytes32) commitIdToLockId; bytes32[] lockIds; bytes32[] commitIds; bytes32 blockHash = blockhash(block.number - 1); uint256 blockHashAsUint = uint256(blockHash); uint256 contractNonce = 0; function commit( string[] memory hopChains, string[] memory hopAssets, string[] memory hopAddresses, string memory dstChain, string memory dstAsset, string memory dstAddress, string memory srcAsset, address srcReceiver, uint timelock, address messenger ) external payable returns (bytes32 commitId) { if (msg.value == 0) { revert FundsNotSent(); } if (timelock <= block.timestamp) { revert NotFutureTimelock(); } contractNonce += 1; commitId = bytes32(blockHashAsUint ^ contractNonce); if (hasPHTLC(commitId)) { revert CommitIdAlreadyExists(); } commitIds.push(commitId); commits[commitId] = PHTLC( dstAddress, dstChain, dstAsset, srcAsset, payable(msg.sender), payable(srcReceiver), bytes32(0), timelock, msg.value, messenger, false, false ); emit TokenCommitted( commitId, hopChains, hopAssets, hopAddresses, dstChain, dstAddress, dstAsset, msg.sender, srcReceiver, srcAsset, msg.value, timelock, messenger ); } function uncommit(bytes32 commitId) external _committed(commitId) returns (bool) { PHTLC storage phtlc = commits[commitId]; if (phtlc.uncommitted) revert AlreadyUncommitted(); if (phtlc.locked) revert AlreadyLocked(); if (phtlc.timelock > block.timestamp) revert NotPassedTimelock(); phtlc.uncommitted = true; (bool success, ) = phtlc.sender.call{ value: phtlc.amount }(''); require(success, 'Transfer failed'); emit TokenUncommitted(commitId); return true; } function lockCommitment( bytes32 commitId, bytes32 hashlock, uint256 timelock ) external _committed(commitId) returns (bytes32 lockId) { lockId = hashlock; if (commits[commitId].uncommitted == true) { revert AlreadyUncommitted(); } if (commits[commitId].locked == true) { revert AlreadyLocked(); } if (hasHTLC(lockId)) { revert LockAlreadyExists(); } if ( msg.sender == commits[commitId].sender || msg.sender == commits[commitId].messenger || msg.sender == address(this) ) { commits[commitId].locked = true; commits[commitId].lockId = hashlock; locks[lockId] = HTLC( commits[commitId].dstAddress, commits[commitId].dstChain, commits[commitId].dstAsset, commits[commitId].srcAsset, payable(commits[commitId].sender), commits[commitId].srcReceiver, hashlock, 0x0, commits[commitId].amount, timelock, false, false ); lockIds.push(hashlock); emit TokenLocked( hashlock, commits[commitId].dstChain, commits[commitId].dstAddress, commits[commitId].dstAsset, commits[commitId].sender, commits[commitId].srcReceiver, commits[commitId].srcAsset, commits[commitId].amount, timelock, commits[commitId].messenger, commitId ); } else { revert NoAllowance(); } } function lockCommitmentSig( bytes32 commitId, lockCommitmentMsg memory message, uint8 v, bytes32 r, bytes32 s ) external _committed(commitId) returns (bytes32 lockId) { if (verifyMessage(msg.sender, message, v, r, s)) { lockId = this.lockCommitment(commitId, message.hashlock, message.timelock); return lockId; } else { revert InvalidSigniture(); } } function lock( bytes32 hashlock, uint256 timelock, address payable srcReceiver, string memory srcAsset, string memory dstChain, string memory dstAddress, string memory dstAsset, bytes32 commitId, address messenger ) external payable returns (bytes32 lockId) { if (msg.value == 0) { revert FundsNotSent(); } if (timelock <= block.timestamp) { revert NotFutureTimelock(); } if (hasHTLC(hashlock)) { revert LockAlreadyExists(); } locks[hashlock] = HTLC( dstAddress, dstChain, dstAsset, srcAsset, payable(msg.sender), srcReceiver, hashlock, 0x0, msg.value, timelock, false, false ); lockId = hashlock; lockIds.push(hashlock); commitIdToLockId[commitId] = lockId; emit TokenLocked( hashlock, dstChain, dstAddress, dstAsset, msg.sender, srcReceiver, srcAsset, msg.value, timelock, messenger, commitId ); if (messenger != address(0)) { uint256 codeSize; assembly { codeSize := extcodesize(messenger) } if (codeSize > 0) { try IMessenger(messenger).notify( commitId, hashlock, dstChain, dstAsset, dstAddress, srcAsset, payable(msg.sender), srcReceiver, msg.value, timelock, address(0) ) { // Notify successful } catch Error(string memory reason) { revert(reason); } catch (bytes memory lowLevelData) { emit LowLevelErrorOccurred(lowLevelData); revert('IMessenger notify failed'); } } else { revert NoMessenger(); } } } function redeem(bytes32 lockId, uint256 secret) external _locked(lockId) returns (bool) { HTLC storage htlc = locks[lockId]; if (htlc.hashlock != sha256(abi.encodePacked(secret))) revert HashlockNotMatch(); if (htlc.unlocked) revert AlreadyUnlocked(); if (htlc.redeemed) revert AlreadyRedeemed(); htlc.secret = secret; htlc.redeemed = true; (bool success, ) = htlc.srcReceiver.call{ value: htlc.amount }(''); require(success, 'Transfer failed'); emit TokenRedeemed(lockId, msg.sender); return true; } function unlock(bytes32 lockId) external _locked(lockId) returns (bool) { HTLC storage htlc = locks[lockId]; if (htlc.unlocked) revert AlreadyUnlocked(); if (htlc.redeemed) revert AlreadyRedeemed(); if (htlc.timelock > block.timestamp) revert NotPassedTimelock(); htlc.unlocked = true; (bool success, ) = htlc.sender.call{ value: htlc.amount }(''); require(success, 'Transfer failed'); emit TokenUnlocked(lockId); return true; } function getLockDetails(bytes32 lockId) public view returns (HTLC memory) { if (!hasHTLC(lockId)) { HTLC memory emptyHTLC = HTLC({ dstAddress: '', dstChain: '', dstAsset: '', srcAsset: '', sender: payable(address(0)), srcReceiver: payable(address(0)), hashlock: bytes32(0x0), secret: uint256(0), amount: uint256(0), timelock: uint256(0), redeemed: false, unlocked: false }); return emptyHTLC; } HTLC storage htlc = locks[lockId]; return htlc; } function getCommitDetails(bytes32 commitId) public view returns (PHTLC memory) { if (!hasPHTLC(commitId)) { PHTLC memory emptyPHTLC = PHTLC({ dstAddress: '', dstChain: '', dstAsset: '', srcAsset: '', sender: payable(address(0)), srcReceiver: payable(address(0)), lockId: bytes32(0), timelock: uint256(0), amount: uint256(0), messenger: address(0), locked: false, uncommitted: false }); return emptyPHTLC; } PHTLC storage phtlc = commits[commitId]; return phtlc; } function hasPHTLC(bytes32 commitId) internal view returns (bool exists) { exists = (commits[commitId].sender != address(0)); } function hasHTLC(bytes32 lockId) internal view returns (bool exists) { exists = (locks[lockId].sender != address(0)); } function getLocks(address senderAddr) public view returns (bytes32[] memory) { uint count = 0; for (uint i = 0; i < lockIds.length; i++) { HTLC memory htlc = locks[lockIds[i]]; if (htlc.sender == senderAddr) { count++; } } bytes32[] memory result = new bytes32[](count); uint j = 0; for (uint i = 0; i < lockIds.length; i++) { if (locks[lockIds[i]].sender == senderAddr) { result[j] = lockIds[i]; j++; } } return result; } function getCommits(address senderAddr) public view returns (bytes32[] memory) { uint count = 0; for (uint i = 0; i < commitIds.length; i++) { PHTLC memory phtlc = commits[commitIds[i]]; if (phtlc.sender == senderAddr) { count++; } } bytes32[] memory result = new bytes32[](count); uint j = 0; for (uint i = 0; i < commitIds.length; i++) { if (commits[commitIds[i]].sender == senderAddr) { result[j] = commitIds[i]; j++; } } return result; } function getLockIdByCommitId(bytes32 commitId) public view returns (bytes32) { return commitIdToLockId[commitId]; } function hashDomain(EIP712Domain memory domain) public pure returns (bytes32) { return keccak256( abi.encode( keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)'), keccak256(bytes(domain.name)), keccak256(bytes(domain.version)), domain.chainId, domain.verifyingContract, domain.salt ) ); } // Hashes an EIP712 message struct function hashMessage(lockCommitmentMsg memory message) public pure returns (bytes32) { return keccak256( abi.encode( keccak256('lockCommitmentMsg(bytes32 hashlock,uint256 timelock)'), message.hashlock, message.timelock ) ); } // Verifies an EIP712 message signature function verifyMessage( address sender, lockCommitmentMsg memory message, uint8 v, bytes32 r, bytes32 s ) public view returns (bool) { bytes32 digest = keccak256(abi.encodePacked('\x19\x01', DOMAIN_SEPARATOR, hashMessage(message))); address recoveredAddress = ecrecover(digest, v, r, s); return (recoveredAddress == sender); } }
@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
@openzeppelin/contracts/utils/cryptography/ECDSA.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @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 } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile 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 {MessageHashUtils-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] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { 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. /// @solidity memory-safe-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 { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile 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 {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); 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] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // 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, s); } // 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, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @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, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
Compiler Settings
{"viaIR":true,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{},"evmVersion":"paris"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"error","name":"AlreadyLocked","inputs":[]},{"type":"error","name":"AlreadyRedeemed","inputs":[]},{"type":"error","name":"AlreadyUncommitted","inputs":[]},{"type":"error","name":"AlreadyUnlocked","inputs":[]},{"type":"error","name":"CommitIdAlreadyExists","inputs":[]},{"type":"error","name":"CommitmentNotExists","inputs":[]},{"type":"error","name":"FundsNotSent","inputs":[]},{"type":"error","name":"HashlockNotMatch","inputs":[]},{"type":"error","name":"InvalidSigniture","inputs":[]},{"type":"error","name":"LockAlreadyExists","inputs":[]},{"type":"error","name":"LockNotExists","inputs":[]},{"type":"error","name":"NoAllowance","inputs":[]},{"type":"error","name":"NoMessenger","inputs":[]},{"type":"error","name":"NotFutureTimelock","inputs":[]},{"type":"error","name":"NotPassedTimelock","inputs":[]},{"type":"event","name":"LowLevelErrorOccurred","inputs":[{"type":"bytes","name":"lowLevelData","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"TokenCommitted","inputs":[{"type":"bytes32","name":"commitId","internalType":"bytes32","indexed":false},{"type":"string[]","name":"hopChains","internalType":"string[]","indexed":false},{"type":"string[]","name":"hopAssets","internalType":"string[]","indexed":false},{"type":"string[]","name":"hopAddresses","internalType":"string[]","indexed":false},{"type":"string","name":"dstChain","internalType":"string","indexed":false},{"type":"string","name":"dstAddress","internalType":"string","indexed":false},{"type":"string","name":"dstAsset","internalType":"string","indexed":false},{"type":"address","name":"sender","internalType":"address","indexed":false},{"type":"address","name":"srcReceiver","internalType":"address","indexed":false},{"type":"string","name":"srcAsset","internalType":"string","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"timelock","internalType":"uint256","indexed":false},{"type":"address","name":"messenger","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"TokenLocked","inputs":[{"type":"bytes32","name":"hashlock","internalType":"bytes32","indexed":true},{"type":"string","name":"dstChain","internalType":"string","indexed":false},{"type":"string","name":"dstAddress","internalType":"string","indexed":false},{"type":"string","name":"dstAsset","internalType":"string","indexed":false},{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"address","name":"srcReceiver","internalType":"address","indexed":true},{"type":"string","name":"srcAsset","internalType":"string","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"timelock","internalType":"uint256","indexed":false},{"type":"address","name":"messenger","internalType":"address","indexed":false},{"type":"bytes32","name":"commitId","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"TokenRedeemed","inputs":[{"type":"bytes32","name":"lockId","internalType":"bytes32","indexed":true},{"type":"address","name":"redeemAddress","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"TokenUncommitted","inputs":[{"type":"bytes32","name":"commitId","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"TokenUnlocked","inputs":[{"type":"bytes32","name":"lockId","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"payable","outputs":[{"type":"bytes32","name":"commitId","internalType":"bytes32"}],"name":"commit","inputs":[{"type":"string[]","name":"hopChains","internalType":"string[]"},{"type":"string[]","name":"hopAssets","internalType":"string[]"},{"type":"string[]","name":"hopAddresses","internalType":"string[]"},{"type":"string","name":"dstChain","internalType":"string"},{"type":"string","name":"dstAsset","internalType":"string"},{"type":"string","name":"dstAddress","internalType":"string"},{"type":"string","name":"srcAsset","internalType":"string"},{"type":"address","name":"srcReceiver","internalType":"address"},{"type":"uint256","name":"timelock","internalType":"uint256"},{"type":"address","name":"messenger","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct LayerswapV8.PHTLC","components":[{"type":"string","name":"dstAddress","internalType":"string"},{"type":"string","name":"dstChain","internalType":"string"},{"type":"string","name":"dstAsset","internalType":"string"},{"type":"string","name":"srcAsset","internalType":"string"},{"type":"address","name":"sender","internalType":"address payable"},{"type":"address","name":"srcReceiver","internalType":"address payable"},{"type":"bytes32","name":"lockId","internalType":"bytes32"},{"type":"uint256","name":"timelock","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"messenger","internalType":"address"},{"type":"bool","name":"locked","internalType":"bool"},{"type":"bool","name":"uncommitted","internalType":"bool"}]}],"name":"getCommitDetails","inputs":[{"type":"bytes32","name":"commitId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"","internalType":"bytes32[]"}],"name":"getCommits","inputs":[{"type":"address","name":"senderAddr","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct LayerswapV8.HTLC","components":[{"type":"string","name":"dstAddress","internalType":"string"},{"type":"string","name":"dstChain","internalType":"string"},{"type":"string","name":"dstAsset","internalType":"string"},{"type":"string","name":"srcAsset","internalType":"string"},{"type":"address","name":"sender","internalType":"address payable"},{"type":"address","name":"srcReceiver","internalType":"address payable"},{"type":"bytes32","name":"hashlock","internalType":"bytes32"},{"type":"uint256","name":"secret","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"timelock","internalType":"uint256"},{"type":"bool","name":"redeemed","internalType":"bool"},{"type":"bool","name":"unlocked","internalType":"bool"}]}],"name":"getLockDetails","inputs":[{"type":"bytes32","name":"lockId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getLockIdByCommitId","inputs":[{"type":"bytes32","name":"commitId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"","internalType":"bytes32[]"}],"name":"getLocks","inputs":[{"type":"address","name":"senderAddr","internalType":"address"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"hashDomain","inputs":[{"type":"tuple","name":"domain","internalType":"struct EIP712Domain","components":[{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"version","internalType":"string"},{"type":"uint256","name":"chainId","internalType":"uint256"},{"type":"address","name":"verifyingContract","internalType":"address"},{"type":"bytes32","name":"salt","internalType":"bytes32"}]}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"hashMessage","inputs":[{"type":"tuple","name":"message","internalType":"struct LayerswapV8.lockCommitmentMsg","components":[{"type":"bytes32","name":"hashlock","internalType":"bytes32"},{"type":"uint256","name":"timelock","internalType":"uint256"}]}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"bytes32","name":"lockId","internalType":"bytes32"}],"name":"lock","inputs":[{"type":"bytes32","name":"hashlock","internalType":"bytes32"},{"type":"uint256","name":"timelock","internalType":"uint256"},{"type":"address","name":"srcReceiver","internalType":"address payable"},{"type":"string","name":"srcAsset","internalType":"string"},{"type":"string","name":"dstChain","internalType":"string"},{"type":"string","name":"dstAddress","internalType":"string"},{"type":"string","name":"dstAsset","internalType":"string"},{"type":"bytes32","name":"commitId","internalType":"bytes32"},{"type":"address","name":"messenger","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes32","name":"lockId","internalType":"bytes32"}],"name":"lockCommitment","inputs":[{"type":"bytes32","name":"commitId","internalType":"bytes32"},{"type":"bytes32","name":"hashlock","internalType":"bytes32"},{"type":"uint256","name":"timelock","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes32","name":"lockId","internalType":"bytes32"}],"name":"lockCommitmentSig","inputs":[{"type":"bytes32","name":"commitId","internalType":"bytes32"},{"type":"tuple","name":"message","internalType":"struct LayerswapV8.lockCommitmentMsg","components":[{"type":"bytes32","name":"hashlock","internalType":"bytes32"},{"type":"uint256","name":"timelock","internalType":"uint256"}]},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"redeem","inputs":[{"type":"bytes32","name":"lockId","internalType":"bytes32"},{"type":"uint256","name":"secret","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"uncommit","inputs":[{"type":"bytes32","name":"commitId","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"unlock","inputs":[{"type":"bytes32","name":"lockId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"verifyMessage","inputs":[{"type":"address","name":"sender","internalType":"address"},{"type":"tuple","name":"message","internalType":"struct LayerswapV8.lockCommitmentMsg","components":[{"type":"bytes32","name":"hashlock","internalType":"bytes32"},{"type":"uint256","name":"timelock","internalType":"uint256"}]},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]}]
Contract Creation Code
0x60806040908082523462000187576000194301438111620001715740806006556007556000908160085560208101906b098c2f2cae4e6eec2e040ac760a31b8252600c81526200004f816200018c565b51902082516001600160401b039390919060a08301858111848210176200015d578082526200007e816200018c565b600b81526a098c2f2cae4e6eec2e0ac760ab1b60c08501528352805192620000a6846200018c565b600184526020840190603160f81b825284602082015246838201523060608201528360808201525160208151910120935190209181519260208401947fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac5647286528385015260608401524660808401523060a084015260c083015260c0825260e082019482861090861117620001495784905251902090556130049081620001bf8239f35b634e487b7160e01b84526041600452602484fd5b634e487b7160e01b85526041600452602485fd5b634e487b7160e01b600052601160045260246000fd5b600080fd5b604081019081106001600160401b03821117620001a857604052565b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c8063255f31541461253c5780632ea3b73c1461238e57806339e35271146123645780633b9c1f5b1461226f578063592b6ad714612227578063673da154146120f6578063719f308914611f2c5780638f5a07f914611ecf578063b4b2279414611e93578063c5bea8b5146116bb578063da76bb3814610d20578063def944071461044c578063ec9b5b3a14610342578063f2062624146101ed5763f5a1862a146100c257600080fd5b346101ea5760203660031901126101ea57600435906100f982600052600260205260018060a01b0360046040600020015416151590565b156101d8578181526002602052604081209160098301805460ff8160a81c166101c65760ff8160a01c166101b457600785015442106101a25760ff60a81b1916600160a81b1790556004830154600890930154602093610175918491829182918291906001600160a01b03165af161016f612d7a565b50612daa565b7fa123e15752679aa06522e49c50e26d336ea83e1aa2e8ecdc4a32f437a474d1366040519280a260018152f35b60405163b3f711f760e01b8152600490fd5b6040516317c3335f60e21b8152600490fd5b604051630e4a482d60e11b8152600490fd5b604051630bfa77dd60e41b8152600490fd5b80fd5b50346101ea576020906003199082823601126101ea576004356001600160401b039283821161033e5760a090823603011261033a576040519160a083018381108582111761031f57604052816004013584811161033a576102549060043691850101612761565b83526024820135908482116101ea57506102749060043691840101612761565b918285820152604482013591826040830152606481013560018060a01b0381169182820361033557608491606085015201359182608082015251868151910120938681519101209260405193878501957fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472875260408601526060850152608084015260a083015260c082015260c0815260e08101928184109084111761031f57826040525190208152f35b634e487b7160e01b600052604160045260246000fd5b600080fd5b5080fd5b8280fd5b50346101ea5760203660031901126101ea576004359061037a82600052600160205260018060a01b0360046040600020015416151590565b1561043a5781815260016020526040812091600a8301805460ff8160081c166104285760ff811661041657600985015442106101a25761ff00191661010017905560048301546008909301546020936103e9918491829182918291906001600160a01b03165af161016f612d7a565b7f3d4cedda486476ed25b0bd452211f1c4b1af03b25ad9d223a96238f84ce640f46040519280a260018152f35b6040516306d3830f60e21b8152600490fd5b6040516328486b6360e11b8152600490fd5b604051632254ea3d60e11b8152600490fd5b506101403660031901126101ea576004356001600160401b03811161033a576104799036906004016127bf565b60249081356001600160401b038111610d1c5761049a9036906004016127bf565b916044356001600160401b038111610d18576104ba9036906004016127bf565b6064356001600160401b038111610d14576104d9903690600401612761565b906084356001600160401b038111610d10576104f9903690600401612761565b60a4356001600160401b038111610d0c57610518903690600401612761565b60c4356001600160401b038111610d0857610537903690600401612761565b9360e435936001600160a01b03851685036103355761012435966001600160a01b0388168803610335573415610cf65742610104351115610ce45760085460018101809111610cd157600881905560075418600081815260026020526040902060040154909b906001600160a01b0316610cbf57600554600160401b811015610caa576105e56105ce828f93600101600555612b01565b819391549060031b91821b91600019901b19161790565b9055604051916105f483612680565b85835284602084015286604084015288606084015233608084015260018060a01b03881660a08401528160c08401526101043560e08401523461010084015260018060a01b038a1661012084015281610140840152816101608401528c82526002602052604082209183518051906001600160401b038211610b0a57819061067c865461289b565b601f8111610c5c575b50602090601f8311600114610bf3578492610be8575b50508160011b916000199060031b1c19161783555b60208401518051906001600160401b038211610b0a5781906106d5600187015461289b565b601f8111610b97575b50602090601f8311600114610b28578492610b1d575b50508160011b916000199060031b1c19161760018401555b60408401518051906001600160401b038211610b0a578190610731600287015461289b565b601f8111610ab9575b50602090601f8311600114610a4f578492610a44575b50508160011b916000199060031b1c19161760028401555b60608401518051926001600160401b038411610a32575090829161078f600386015461289b565b601f81116109df575b50602091601f84116001146109705792610965575b50508160011b916000199060031b1c19161760038201555b60048101600160a01b60019003608084015116906001600160601b0360a01b91828254161790556005820190600160a01b6001900360a0850151169082541617905560c0820151600682015560e08201516007820155610100820151600882015560090190600160a01b60019003610120820151169082549160ff60a01b610140830151151560a01b169160ff60a81b906101600151151560a81b169269ffffffffffffffffffff60b01b1617171790556040519889986101a08c8b528060208c01528a0161089391612f71565b89810360408b01526108a491612f71565b88810360608a01526108b591612f71565b87810360808901526108c691612609565b86810360a08801526108d791612609565b85810360c08701526108e891612609565b3360e08601526001600160a01b0390911661010085015283810361012085015261091191612609565b34610140840152610104356101608401526001600160a01b039091166101808301527f625ba51e51c5f2c394db4494f428998d9a34cd2f81e1ff9f134570a67f92ac469291900390a1604051908152602090f35b0151905038806107ad565b6003860181526020812090945091905b601f19841685106109c4576001945083601f198116106109ab575b505050811b0160038201556107c5565b015160001960f88460031b161c1916905538808061099b565b81810151835560209485019460019093019290910190610980565b9091925060038501835260208320601f850160051c810160208610610a2b575b9085949392915b601f830160051c82018110610a1c575050610798565b60008155869550600101610a06565b50806109ff565b634e487b7160e01b8352604160045282fd5b015190503880610750565b600287018552602085209250601f198416855b818110610aa15750908460019594939210610a88575b505050811b016002840155610768565b015160001960f88460031b161c19169055388080610a78565b92936020600181928786015181550195019301610a62565b90915060028601845260208420601f840160051c810160208510610b03575b90849392915b601f830160051c82018110610af457505061073a565b60008155859450600101610ade565b5080610ad8565b5050634e487b7160e01b81526041600452fd5b0151905038806106f4565b9250600186018452602084209084935b601f1984168510610b7c576001945083601f19811610610b63575b505050811b01600184015561070c565b015160001960f88460031b161c19169055388080610b53565b81810151835560209485019460019093019290910190610b38565b90915060018601845260208420601f840160051c810160208510610be1575b90849392915b601f830160051c82018110610bd25750506106de565b60008155859450600101610bbc565b5080610bb6565b01519050388061069b565b9250858452602084209084935b601f1984168510610c41576001945083601f19811610610c28575b505050811b0183556106b0565b015160001960f88460031b161c19169055388080610c1b565b81810151835560209485019460019093019290910190610c00565b90915085845260208420601f840160051c810160208510610ca3575b90849392915b601f830160051c82018110610c94575050610685565b60008155859450600101610c7e565b5080610c78565b82634e487b7160e01b60005260416004526000fd5b604051637870919b60e01b8152600490fd5b50634e487b7160e01b8b5260116004528afd5b604051633dd8280960e21b8152600490fd5b604051636f8ab38d60e11b8152600490fd5b8880fd5b8780fd5b8680fd5b8580fd5b8480fd5b8380fd5b506101203660031901126101ea57604435906001600160a01b03821682036101ea576064356001600160401b03811161033a57610d61903690600401612761565b916084356001600160401b03811161033e57610d81903690600401612761565b9060a4356001600160401b038111610d1c57610da1903690600401612761565b9360c4356001600160401b038111610d1857610dc1903690600401612761565b94610104356001600160a01b0381169003610d18573415610cf657426024351115610ce45760048035600090815260016020526040902001546001600160a01b03166116a957604051610e1381612680565b81815284602082015286604082015282606082015233608082015260018060a01b03841660a082015260043560c08201528560e0820152346101008201526024356101208201528561014082015285610160820152600435865260016020526040862081518051906001600160401b038211611440578190610e95845461289b565b601f811161165c575b50602090601f83116001146115f3578a926115e8575b50508160011b916000199060031b1c19161781555b60208201518051906001600160401b038211611440578190610eee600185015461289b565b601f8111611598575b50602090601f8311600114611529578a9261151e575b50508160011b916000199060031b1c19161760018201555b60408201518051906001600160401b038211611440578190610f4a600285015461289b565b601f81116114ce575b50602090601f831160011461145f578a92611454575b50508160011b916000199060031b1c19161760028201555b60608201518051906001600160401b03821161144057610fa4600384015461289b565b601f81116113fc575b50602090601f831160011461138557928261016093600a9361108897968d9261137a575b50508160011b916000199060031b1c19161760038201555b6004810160018060a01b03608086015116906001600160601b0360a01b9182825416179055600582019060018060a01b0360a0870151169082541617905560c0840151600682015560e084015160078201556101008401516008820155610120840151600982015501916110706101408201511515849060ff801983541691151516179055565b0151815461ff00191690151560081b61ff0016179055565b611093600435612eda565b60e43585526003602052600435604086205560405161010081526110ee6110e06110d26110c4610100850189612609565b848103602086015285612609565b838103604085015289612609565b828103606084015284612609565b34608083015260243560a08301526001600160a01b0361010435811660c084015260e43560e08401528516913391600435917f24804913990b29b6ec6950b6dce63c2cd286bae5e010ee05cbdeaacc09281d5c9181900390a4610104356001600160a01b0316611165575b60206040516004358152f35b610104353b1561136857610104356001600160a01b03163b15610d1857916111fe8594926111ec6111c8956111da6040519a8b988998635e863a5b60e01b8a5260e43560048b015260043560248b015261016060448b01526101648a0190612609565b8881036003190160648a015290612609565b86810360031901608488015290612609565b8481036003190160a486015290612609565b903360c484015260018060a01b031660e4830152346101048301526024356101248301528361014483015203818360018060a01b0361010435165af1918261133d575b5090611331578060033d11611320575b506308c379a0146112e5575b7f7b5bdb2f87e8e20f082bba9be5f7e870728f9bba18540559ccdcdcbb1fc5a08761129d611289612d7a565b604051918291602083526020830190612609565b0390a160405162461bcd60e51b815260206004820152601860248201527f494d657373656e676572206e6f74696679206661696c656400000000000000006044820152606490fd5b6112ed612f00565b806112f8575061125d565b60405162461bcd60e51b81526020600482015290819061131c906024830190612609565b0390fd5b9050600481803e5160e01c38611251565b50388080808080611159565b6001600160401b0381116113545760405238611241565b634e487b7160e01b82526041600452602482fd5b604051633127e9d760e11b8152600490fd5b015190503880610fd1565b90600384018a5260208a20918a5b601f19851681106113e4575083600a9361108897969360019361016097601f198116106113cb575b505050811b016003820155610fe9565b015160001960f88460031b161c191690553880806113bb565b91926020600181928685015181550194019201611393565b600384018a5260208a20601f840160051c810160208510611439575b601f830160051c8201811061142e575050610fad565b8b8155600101611418565b5080611418565b634e487b7160e01b89526041600452602489fd5b015190503880610f69565b9250600284018a5260208a20908a935b601f19841685106114b3576001945083601f1981161061149a575b505050811b016002820155610f81565b015160001960f88460031b161c1916905538808061148a565b8181015183556020948501946001909301929091019061146f565b909150600284018a5260208a20601f840160051c810160208510611517575b90849392915b601f830160051c82018110611509575050610f53565b8c81558594506001016114f3565b50806114ed565b015190503880610f0d565b9250600184018a5260208a20908a935b601f198416851061157d576001945083601f19811610611564575b505050811b016001820155610f25565b015160001960f88460031b161c19169055388080611554565b81810151835560209485019460019093019290910190611539565b909150600184018a5260208a20601f840160051c8101602085106115e1575b90849392915b601f830160051c820181106115d3575050610ef7565b8c81558594506001016115bd565b50806115b7565b015190503880610eb4565b9250838a5260208a20908a935b601f1984168510611641576001945083601f19811610611628575b505050811b018155610ec9565b015160001960f88460031b161c1916905538808061161b565b81810151835560209485019460019093019290910190611600565b909150838a5260208a20601f840160051c8101602085106116a2575b90849392915b601f830160051c82018110611694575050610e9e565b8c815585945060010161167e565b5080611678565b60405163748d150960e01b8152600490fd5b50346101ea5760603660031901126101ea5760048035600090815260026020526040902001546001600160a01b0316156101d85760043581526002602052600160ff600960408420015460a81c161515146101c65760043581526002602052600160ff600960408420015460a01c161515146101b4576024356000908152600160205260409020600401546001600160a01b03166116a957600435815260026020526040812060018060a01b036004820154163314908115611e7c575b508015611e73575b15611e61576004803582526002602052604080832060098101805460ff60a01b1916600160a01b17905560243560068201559182015460058301546008840154925194936001600160a01b039182169290911690600390611840906117e488612680565b6040516117fc816117f581856128d5565b03826126ed565b8852604051611812816117f581600186016128d5565b602089015260405161182b816117f581600286016128d5565b60408901526117f560405180948193016128d5565b6060860152608085015260a084015260243560c08401528160e0840152610100830152604435610120830152806101408301528061016083015260243581526001602052604081209180519283516001600160401b038111611c11576118a6825461289b565b601f8111611e20575b506020601f8211600114611dba5784958293949592611daf575b50508160011b916000199060031b1c19161781555b60208201519283516001600160401b03811161135457611901600184015461289b565b601f8111611d6b575b506020601f8211600114611cff5782939495829392611cf4575b50508160011b916000199060031b1c19161760018301555b60408301519283516001600160401b038111611ce05761195f600285015461289b565b601f8111611c9c575b506020601f8211600114611c305783949582939492611c25575b50508160011b916000199060031b1c19161760028401555b60608101519283516001600160401b038111611c11576119bd600383015461289b565b601f8111611bcd575b506020601f8211600114611b6f57611a8893928261016093600a93604099899261137a5750508160011b916000199060031b1c19161760038201556004810160018060a01b03608086015116906001600160601b0360a01b9182825416179055600582019060018060a01b0360a0870151169082541617905560c0840151600682015560e084015160078201556101008401516008820155610120840151600982015501916110706101408201511515849060ff801983541691151516179055565b611a93602435612eda565b600435815260026020522060018060a01b0360048201541660018060a01b03600583015416917f24804913990b29b6ec6950b6dce63c2cd286bae5e010ee05cbdeaacc09281d5c60088201549160018060a01b03600982015416611b406040519261010084526003611b31611b20611b126101008801600186016128d5565b8781036020890152846128d5565b8681036040880152600284016128d5565b918583036060870152016128d5565b93608083015260443560a083015260c082015260043560e082015280602435930390a460206040516024358152f35b6003830185526020852095855b601f1984168110611bb5575092600183604098600a94611a88989761016097601f198116106113cb57505050811b016003820155610fe9565b82820151885560019097019660209283019201611b7c565b60038301855260208520601f830160051c810160208410611c0a575b601f830160051c82018110611bff5750506119c6565b868155600101611be9565b5080611be9565b634e487b7160e01b84526041600452602484fd5b015190503880611982565b6002850184526020842090845b601f1984168110611c84575060019394959683601f19811610611c6b575b505050811b01600284015561199a565b015160001960f88460031b161c19169055388080611c5b565b9091602060018192858b015181550193019101611c3d565b60028501845260208420601f830160051c810160208410611cd9575b601f830160051c82018110611cce575050611968565b858155600101611cb8565b5080611cb8565b634e487b7160e01b83526041600452602483fd5b015190503880611924565b6001840183526020832090835b601f1984168110611d53575060019394959683601f19811610611d3a575b505050811b01600183015561193c565b015160001960f88460031b161c19169055388080611d2a565b9091602060018192858b015181550193019101611d0c565b60018401835260208320601f830160051c810160208410611da8575b601f830160051c82018110611d9d57505061190a565b848155600101611d87565b5080611d87565b0151905038806118c9565b8285526020852090855b601f1984168110611e08575060019394959683601f19811610611def575b505050811b0181556118de565b015160001960f88460031b161c19169055388080611de2565b9091602060018192858b015181550193019101611dc4565b82855260208520601f830160051c810160208410611e5a575b601f830160051c82018110611e4f5750506118af565b868155600101611e39565b5080611e39565b604051631d7eb35960e31b8152600490fd5b50303314611780565b600901546001600160a01b03163314905038611778565b50346101ea5760403660031901126101ea576020611ec7604051611eb68161269c565b600435815260243583820152612e8a565b604051908152f35b50346101ea5760c03660031901126101ea57600435611eed3661270e565b611ef5612736565b6000838152600260205260409020600401549091906001600160a01b0316156101d857602092611ec79260a4359260843592612de8565b50346101ea5760209060206003193601126101ea57611f4961262e565b6004546001600160a01b039390929091841681805b858110611fea5750611f6f90612baa565b9482805b868110611f8c5760405180611f888a82612644565b0390f35b611f9581612b4e565b9054600391821b1c835260018752848460046040862001541614611fbd575b50600101611f73565b8195611fe391611fce600194612b4e565b9054911b1c611fdd828c612bdc565b52612b85565b9490611fb4565b82611ff482612b4e565b9054600391821b1c865260018088526117f561206d60408920936117f56120426040519561202187612680565b604051612032816117f5818c6128d5565b8752604051928380928a016128d5565b8b85015260405161205a816117f58160028a016128d5565b60408501526040519283809287016128d5565b60608201526101608a600484015416928360808401528b60058201541660a0840152600681015460c0840152600781015460e0840152600a600891828101546101008601526009810154610120860152015460ff9182821615156101408601521c161515910152146120e2575b600101611f5e565b906120ee600191612b85565b9190506120da565b50346101ea5760403660031901126101ea5760048035600081815260016020526040902090910154602435906001600160a01b03161561043a57818352602092600184526040812091600683015485836121706040518381019086825284815261215f8161269c565b6040519283928392519283916125e6565b8101039060025afa1561221c5782510361220a57600a830190815460ff8160081c166104285760ff811661041657600785019190915560ff1916600117905560058201546008909201546121d892829182918291906001600160a01b03165af161016f612d7a565b7f0f7c50d316885e5d3719752f760bbbbf7d56363501e721eea4d913e255b632e482604051338152a260405160018152f35b60405163e73bcb3560e01b8152600490fd5b6040513d84823e3d90fd5b50346101ea5760c03660031901126101ea57602061226561224661262e565b61224f3661270e565b90612258612736565b60a4359260843592612cf6565b6040519015158152f35b50346101ea5760203660031901126101ea5761228c600435612bf0565b60405180916020825280516122fa6122b2610180928360208701526101a0860190612609565b6122e56122d1602086015192601f1993848983030160408a0152612609565b604086015183888303016060890152612609565b90606085015190868303016080870152612609565b91608081015160018060a01b0380911660a08601528060a08301511660c086015260c082015160e086015260e08201516101009081870152820151610120908187015282015190610140911681860152810151906101609115158286015201511515908301520390f35b50346101ea5760203660031901126101ea5760406020916004358152600383522054604051908152f35b50346101ea5760209060206003193601126101ea576123ab61262e565b9181806005936005549460018060a01b03809716925b8681106124355750506123d390612baa565b9482805b8681106123ec5760405180611f888a82612644565b6123f581612b01565b9054600391821b1c83526002875284846004604086200154161461241d575b506001016123d7565b819561242e91611fce600194612b01565b9490612414565b8361243f82612b01565b9054600391821b1c8752876117f56124af6002938484526117f561205a60408d209660016040519761247089612680565b604051612481816117f5818e6128d5565b895261249e8a61249760405180958193016128d5565b03836126ed565b880152604051928380928a016128d5565b60608201526101608b600484015416928360808401528c60098189840154169260a09384870152600681015460c0870152600781015460e087015260088101546101008701520154918291821661012086015260ff9283911c16151561014085015260a81c16151591015214612528575b6001016123c1565b91612534600191612b85565b929050612520565b50346101ea5760203660031901126101ea5761255960043561296b565b604051809160208252805161257f6122b2610180928360208701526101a0860190612609565b91608081015160018060a01b0380911660a086015260a08201511660c085015260c081015160e085015260e0810151610100908186015281015161012090818601528101516101409081860152810151906101609115158286015201511515908301520390f35b60005b8381106125f95750506000910152565b81810151838201526020016125e9565b90602091612622815180928185528580860191016125e6565b601f01601f1916010190565b600435906001600160a01b038216820361033557565b602090602060408183019282815285518094520193019160005b82811061266c575050505090565b83518552938101939281019260010161265e565b61018081019081106001600160401b0382111761031f57604052565b604081019081106001600160401b0382111761031f57604052565b602081019081106001600160401b0382111761031f57604052565b608081019081106001600160401b0382111761031f57604052565b90601f801991011681019081106001600160401b0382111761031f57604052565b604090602319011261033557604051906127278261269c565b60243582526044356020830152565b6064359060ff8216820361033557565b6001600160401b03811161031f57601f01601f191660200190565b81601f820112156103355780359061277882612746565b9261278660405194856126ed565b8284526020838301011161033557816000926020809301838601378301015290565b6001600160401b03811161031f5760051b60200190565b81601f82011215610335578035916020916127d9846127a8565b936127e760405195866126ed565b808552838086019160051b8301019280841161033557848301915b8483106128125750505050505090565b82356001600160401b03811161033557869161283384848094890101612761565b815201920191612802565b6040519061284b82612680565b816060815260606020820152606060408201526060808201526101606000918260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201520152565b90600182811c921680156128cb575b60208310146128b557565b634e487b7160e01b600052602260045260246000fd5b91607f16916128aa565b8054600093926128e48261289b565b9182825260209360019160018116908160001461294c575060011461290b575b5050505050565b90939495506000929192528360002092846000945b83861061293857505050500101903880808080612904565b805485870183015294019385908201612920565b60ff19168685015250505090151560051b010191503880808080612904565b61297361283e565b506000818152600160205260409020600401546001600160a01b031615612a71576000526001602052604060ff600a826000208351936129b285612680565b80516129c2816117f581866128d5565b855280516129d7816117f581600187016128d5565b602086015280516129ef816117f581600287016128d5565b8186015251612a05816117f581600386016128d5565b606085015260048101546001600160a01b03908116608086015260058201541660a0850152600681015460c0850152600781015460e085015260088082015461010086015260098201546101208601529101548281161515610140850152901c16151561016082015290565b506040805190612a8082612680565b805190612a8c826126b7565b60009182815283528051612a9f816126b7565b82815260208401528051612ab2816126b7565b8281528184015251612ac3816126b7565b81815260608301528060808301528060a08301528060c08301528060e083015280610100830152806101208301528061014083015261016082015290565b600554811015612b385760056000527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00190600090565b634e487b7160e01b600052603260045260246000fd5b600454811015612b385760046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0190600090565b6000198114612b945760010190565b634e487b7160e01b600052601160045260246000fd5b90612bb4826127a8565b612bc160405191826126ed565b8281528092612bd2601f19916127a8565b0190602036910137565b8051821015612b385760209160051b010190565b612bf861283e565b506000818152600260205260409020600401546001600160a01b031615612a71576000526002602052604060ff81600020825192612c3584612680565b8051612c45816117f581866128d5565b84528051612c5a816117f581600187016128d5565b60208501528051612c72816117f581600287016128d5565b8185015251612c88816117f581600386016128d5565b6060840152600960018060a01b03918260048201541660808601528260058201541660a0860152600681015460c0860152600781015460e086015260088101546101008601520154908116610120840152818160a01c16151561014084015260a81c16151561016082015290565b9360209260809160ff956000968795612d10875491612e8a565b604051908982019261190160f01b84526022830152604282015260428152612d37816126d2565b5190209360405194855216868401526040830152606082015282805260015afa15612d6e57516001600160a01b0390811691161490565b604051903d90823e3d90fd5b3d15612da5573d90612d8b82612746565b91612d9960405193846126ed565b82523d6000602084013e565b606090565b15612db157565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b939092612df6928433612cf6565b15612e785760208151910151906040519263c5bea8b560e01b84526004840152602483015260448201526020816064816000305af1908115612e6c57600091612e3d575090565b90506020813d602011612e64575b81612e58602093836126ed565b81010312610335575190565b3d9150612e4b565b6040513d6000823e3d90fd5b60405163553470cf60e01b8152600490fd5b602081519101516040519060208201927f60a3779ca56ee3eec550d74cf166571491c060455674e514bc4193adcc9e6c1384526040830152606082015260608152612ed4816126d2565b51902090565b600454600160401b81101561031f576105ce816001612efc9301600455612b4e565b9055565b600060443d10612f5d57604051600319913d83016004833e81516001600160401b03918282113d602484011117612f6057818401948551938411612f68573d85010160208487010111612f605750612f5d929101602001906126ed565b90565b949350505050565b50949350505050565b90808251908181526020809101926020808460051b8301019501936000915b848310612fa05750505050505090565b9091929394958480612fbe600193601f198682030187528a51612609565b9801930193019194939290612f9056fea2646970667358221220fba4e1ba9fcad68716e83408b3d43ba3ec07ecd56a0214cade611db99454214264736f6c63430008170033
Deployed ByteCode
0x6080604052600436101561001257600080fd5b6000803560e01c8063255f31541461253c5780632ea3b73c1461238e57806339e35271146123645780633b9c1f5b1461226f578063592b6ad714612227578063673da154146120f6578063719f308914611f2c5780638f5a07f914611ecf578063b4b2279414611e93578063c5bea8b5146116bb578063da76bb3814610d20578063def944071461044c578063ec9b5b3a14610342578063f2062624146101ed5763f5a1862a146100c257600080fd5b346101ea5760203660031901126101ea57600435906100f982600052600260205260018060a01b0360046040600020015416151590565b156101d8578181526002602052604081209160098301805460ff8160a81c166101c65760ff8160a01c166101b457600785015442106101a25760ff60a81b1916600160a81b1790556004830154600890930154602093610175918491829182918291906001600160a01b03165af161016f612d7a565b50612daa565b7fa123e15752679aa06522e49c50e26d336ea83e1aa2e8ecdc4a32f437a474d1366040519280a260018152f35b60405163b3f711f760e01b8152600490fd5b6040516317c3335f60e21b8152600490fd5b604051630e4a482d60e11b8152600490fd5b604051630bfa77dd60e41b8152600490fd5b80fd5b50346101ea576020906003199082823601126101ea576004356001600160401b039283821161033e5760a090823603011261033a576040519160a083018381108582111761031f57604052816004013584811161033a576102549060043691850101612761565b83526024820135908482116101ea57506102749060043691840101612761565b918285820152604482013591826040830152606481013560018060a01b0381169182820361033557608491606085015201359182608082015251868151910120938681519101209260405193878501957fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472875260408601526060850152608084015260a083015260c082015260c0815260e08101928184109084111761031f57826040525190208152f35b634e487b7160e01b600052604160045260246000fd5b600080fd5b5080fd5b8280fd5b50346101ea5760203660031901126101ea576004359061037a82600052600160205260018060a01b0360046040600020015416151590565b1561043a5781815260016020526040812091600a8301805460ff8160081c166104285760ff811661041657600985015442106101a25761ff00191661010017905560048301546008909301546020936103e9918491829182918291906001600160a01b03165af161016f612d7a565b7f3d4cedda486476ed25b0bd452211f1c4b1af03b25ad9d223a96238f84ce640f46040519280a260018152f35b6040516306d3830f60e21b8152600490fd5b6040516328486b6360e11b8152600490fd5b604051632254ea3d60e11b8152600490fd5b506101403660031901126101ea576004356001600160401b03811161033a576104799036906004016127bf565b60249081356001600160401b038111610d1c5761049a9036906004016127bf565b916044356001600160401b038111610d18576104ba9036906004016127bf565b6064356001600160401b038111610d14576104d9903690600401612761565b906084356001600160401b038111610d10576104f9903690600401612761565b60a4356001600160401b038111610d0c57610518903690600401612761565b60c4356001600160401b038111610d0857610537903690600401612761565b9360e435936001600160a01b03851685036103355761012435966001600160a01b0388168803610335573415610cf65742610104351115610ce45760085460018101809111610cd157600881905560075418600081815260026020526040902060040154909b906001600160a01b0316610cbf57600554600160401b811015610caa576105e56105ce828f93600101600555612b01565b819391549060031b91821b91600019901b19161790565b9055604051916105f483612680565b85835284602084015286604084015288606084015233608084015260018060a01b03881660a08401528160c08401526101043560e08401523461010084015260018060a01b038a1661012084015281610140840152816101608401528c82526002602052604082209183518051906001600160401b038211610b0a57819061067c865461289b565b601f8111610c5c575b50602090601f8311600114610bf3578492610be8575b50508160011b916000199060031b1c19161783555b60208401518051906001600160401b038211610b0a5781906106d5600187015461289b565b601f8111610b97575b50602090601f8311600114610b28578492610b1d575b50508160011b916000199060031b1c19161760018401555b60408401518051906001600160401b038211610b0a578190610731600287015461289b565b601f8111610ab9575b50602090601f8311600114610a4f578492610a44575b50508160011b916000199060031b1c19161760028401555b60608401518051926001600160401b038411610a32575090829161078f600386015461289b565b601f81116109df575b50602091601f84116001146109705792610965575b50508160011b916000199060031b1c19161760038201555b60048101600160a01b60019003608084015116906001600160601b0360a01b91828254161790556005820190600160a01b6001900360a0850151169082541617905560c0820151600682015560e08201516007820155610100820151600882015560090190600160a01b60019003610120820151169082549160ff60a01b610140830151151560a01b169160ff60a81b906101600151151560a81b169269ffffffffffffffffffff60b01b1617171790556040519889986101a08c8b528060208c01528a0161089391612f71565b89810360408b01526108a491612f71565b88810360608a01526108b591612f71565b87810360808901526108c691612609565b86810360a08801526108d791612609565b85810360c08701526108e891612609565b3360e08601526001600160a01b0390911661010085015283810361012085015261091191612609565b34610140840152610104356101608401526001600160a01b039091166101808301527f625ba51e51c5f2c394db4494f428998d9a34cd2f81e1ff9f134570a67f92ac469291900390a1604051908152602090f35b0151905038806107ad565b6003860181526020812090945091905b601f19841685106109c4576001945083601f198116106109ab575b505050811b0160038201556107c5565b015160001960f88460031b161c1916905538808061099b565b81810151835560209485019460019093019290910190610980565b9091925060038501835260208320601f850160051c810160208610610a2b575b9085949392915b601f830160051c82018110610a1c575050610798565b60008155869550600101610a06565b50806109ff565b634e487b7160e01b8352604160045282fd5b015190503880610750565b600287018552602085209250601f198416855b818110610aa15750908460019594939210610a88575b505050811b016002840155610768565b015160001960f88460031b161c19169055388080610a78565b92936020600181928786015181550195019301610a62565b90915060028601845260208420601f840160051c810160208510610b03575b90849392915b601f830160051c82018110610af457505061073a565b60008155859450600101610ade565b5080610ad8565b5050634e487b7160e01b81526041600452fd5b0151905038806106f4565b9250600186018452602084209084935b601f1984168510610b7c576001945083601f19811610610b63575b505050811b01600184015561070c565b015160001960f88460031b161c19169055388080610b53565b81810151835560209485019460019093019290910190610b38565b90915060018601845260208420601f840160051c810160208510610be1575b90849392915b601f830160051c82018110610bd25750506106de565b60008155859450600101610bbc565b5080610bb6565b01519050388061069b565b9250858452602084209084935b601f1984168510610c41576001945083601f19811610610c28575b505050811b0183556106b0565b015160001960f88460031b161c19169055388080610c1b565b81810151835560209485019460019093019290910190610c00565b90915085845260208420601f840160051c810160208510610ca3575b90849392915b601f830160051c82018110610c94575050610685565b60008155859450600101610c7e565b5080610c78565b82634e487b7160e01b60005260416004526000fd5b604051637870919b60e01b8152600490fd5b50634e487b7160e01b8b5260116004528afd5b604051633dd8280960e21b8152600490fd5b604051636f8ab38d60e11b8152600490fd5b8880fd5b8780fd5b8680fd5b8580fd5b8480fd5b8380fd5b506101203660031901126101ea57604435906001600160a01b03821682036101ea576064356001600160401b03811161033a57610d61903690600401612761565b916084356001600160401b03811161033e57610d81903690600401612761565b9060a4356001600160401b038111610d1c57610da1903690600401612761565b9360c4356001600160401b038111610d1857610dc1903690600401612761565b94610104356001600160a01b0381169003610d18573415610cf657426024351115610ce45760048035600090815260016020526040902001546001600160a01b03166116a957604051610e1381612680565b81815284602082015286604082015282606082015233608082015260018060a01b03841660a082015260043560c08201528560e0820152346101008201526024356101208201528561014082015285610160820152600435865260016020526040862081518051906001600160401b038211611440578190610e95845461289b565b601f811161165c575b50602090601f83116001146115f3578a926115e8575b50508160011b916000199060031b1c19161781555b60208201518051906001600160401b038211611440578190610eee600185015461289b565b601f8111611598575b50602090601f8311600114611529578a9261151e575b50508160011b916000199060031b1c19161760018201555b60408201518051906001600160401b038211611440578190610f4a600285015461289b565b601f81116114ce575b50602090601f831160011461145f578a92611454575b50508160011b916000199060031b1c19161760028201555b60608201518051906001600160401b03821161144057610fa4600384015461289b565b601f81116113fc575b50602090601f831160011461138557928261016093600a9361108897968d9261137a575b50508160011b916000199060031b1c19161760038201555b6004810160018060a01b03608086015116906001600160601b0360a01b9182825416179055600582019060018060a01b0360a0870151169082541617905560c0840151600682015560e084015160078201556101008401516008820155610120840151600982015501916110706101408201511515849060ff801983541691151516179055565b0151815461ff00191690151560081b61ff0016179055565b611093600435612eda565b60e43585526003602052600435604086205560405161010081526110ee6110e06110d26110c4610100850189612609565b848103602086015285612609565b838103604085015289612609565b828103606084015284612609565b34608083015260243560a08301526001600160a01b0361010435811660c084015260e43560e08401528516913391600435917f24804913990b29b6ec6950b6dce63c2cd286bae5e010ee05cbdeaacc09281d5c9181900390a4610104356001600160a01b0316611165575b60206040516004358152f35b610104353b1561136857610104356001600160a01b03163b15610d1857916111fe8594926111ec6111c8956111da6040519a8b988998635e863a5b60e01b8a5260e43560048b015260043560248b015261016060448b01526101648a0190612609565b8881036003190160648a015290612609565b86810360031901608488015290612609565b8481036003190160a486015290612609565b903360c484015260018060a01b031660e4830152346101048301526024356101248301528361014483015203818360018060a01b0361010435165af1918261133d575b5090611331578060033d11611320575b506308c379a0146112e5575b7f7b5bdb2f87e8e20f082bba9be5f7e870728f9bba18540559ccdcdcbb1fc5a08761129d611289612d7a565b604051918291602083526020830190612609565b0390a160405162461bcd60e51b815260206004820152601860248201527f494d657373656e676572206e6f74696679206661696c656400000000000000006044820152606490fd5b6112ed612f00565b806112f8575061125d565b60405162461bcd60e51b81526020600482015290819061131c906024830190612609565b0390fd5b9050600481803e5160e01c38611251565b50388080808080611159565b6001600160401b0381116113545760405238611241565b634e487b7160e01b82526041600452602482fd5b604051633127e9d760e11b8152600490fd5b015190503880610fd1565b90600384018a5260208a20918a5b601f19851681106113e4575083600a9361108897969360019361016097601f198116106113cb575b505050811b016003820155610fe9565b015160001960f88460031b161c191690553880806113bb565b91926020600181928685015181550194019201611393565b600384018a5260208a20601f840160051c810160208510611439575b601f830160051c8201811061142e575050610fad565b8b8155600101611418565b5080611418565b634e487b7160e01b89526041600452602489fd5b015190503880610f69565b9250600284018a5260208a20908a935b601f19841685106114b3576001945083601f1981161061149a575b505050811b016002820155610f81565b015160001960f88460031b161c1916905538808061148a565b8181015183556020948501946001909301929091019061146f565b909150600284018a5260208a20601f840160051c810160208510611517575b90849392915b601f830160051c82018110611509575050610f53565b8c81558594506001016114f3565b50806114ed565b015190503880610f0d565b9250600184018a5260208a20908a935b601f198416851061157d576001945083601f19811610611564575b505050811b016001820155610f25565b015160001960f88460031b161c19169055388080611554565b81810151835560209485019460019093019290910190611539565b909150600184018a5260208a20601f840160051c8101602085106115e1575b90849392915b601f830160051c820181106115d3575050610ef7565b8c81558594506001016115bd565b50806115b7565b015190503880610eb4565b9250838a5260208a20908a935b601f1984168510611641576001945083601f19811610611628575b505050811b018155610ec9565b015160001960f88460031b161c1916905538808061161b565b81810151835560209485019460019093019290910190611600565b909150838a5260208a20601f840160051c8101602085106116a2575b90849392915b601f830160051c82018110611694575050610e9e565b8c815585945060010161167e565b5080611678565b60405163748d150960e01b8152600490fd5b50346101ea5760603660031901126101ea5760048035600090815260026020526040902001546001600160a01b0316156101d85760043581526002602052600160ff600960408420015460a81c161515146101c65760043581526002602052600160ff600960408420015460a01c161515146101b4576024356000908152600160205260409020600401546001600160a01b03166116a957600435815260026020526040812060018060a01b036004820154163314908115611e7c575b508015611e73575b15611e61576004803582526002602052604080832060098101805460ff60a01b1916600160a01b17905560243560068201559182015460058301546008840154925194936001600160a01b039182169290911690600390611840906117e488612680565b6040516117fc816117f581856128d5565b03826126ed565b8852604051611812816117f581600186016128d5565b602089015260405161182b816117f581600286016128d5565b60408901526117f560405180948193016128d5565b6060860152608085015260a084015260243560c08401528160e0840152610100830152604435610120830152806101408301528061016083015260243581526001602052604081209180519283516001600160401b038111611c11576118a6825461289b565b601f8111611e20575b506020601f8211600114611dba5784958293949592611daf575b50508160011b916000199060031b1c19161781555b60208201519283516001600160401b03811161135457611901600184015461289b565b601f8111611d6b575b506020601f8211600114611cff5782939495829392611cf4575b50508160011b916000199060031b1c19161760018301555b60408301519283516001600160401b038111611ce05761195f600285015461289b565b601f8111611c9c575b506020601f8211600114611c305783949582939492611c25575b50508160011b916000199060031b1c19161760028401555b60608101519283516001600160401b038111611c11576119bd600383015461289b565b601f8111611bcd575b506020601f8211600114611b6f57611a8893928261016093600a93604099899261137a5750508160011b916000199060031b1c19161760038201556004810160018060a01b03608086015116906001600160601b0360a01b9182825416179055600582019060018060a01b0360a0870151169082541617905560c0840151600682015560e084015160078201556101008401516008820155610120840151600982015501916110706101408201511515849060ff801983541691151516179055565b611a93602435612eda565b600435815260026020522060018060a01b0360048201541660018060a01b03600583015416917f24804913990b29b6ec6950b6dce63c2cd286bae5e010ee05cbdeaacc09281d5c60088201549160018060a01b03600982015416611b406040519261010084526003611b31611b20611b126101008801600186016128d5565b8781036020890152846128d5565b8681036040880152600284016128d5565b918583036060870152016128d5565b93608083015260443560a083015260c082015260043560e082015280602435930390a460206040516024358152f35b6003830185526020852095855b601f1984168110611bb5575092600183604098600a94611a88989761016097601f198116106113cb57505050811b016003820155610fe9565b82820151885560019097019660209283019201611b7c565b60038301855260208520601f830160051c810160208410611c0a575b601f830160051c82018110611bff5750506119c6565b868155600101611be9565b5080611be9565b634e487b7160e01b84526041600452602484fd5b015190503880611982565b6002850184526020842090845b601f1984168110611c84575060019394959683601f19811610611c6b575b505050811b01600284015561199a565b015160001960f88460031b161c19169055388080611c5b565b9091602060018192858b015181550193019101611c3d565b60028501845260208420601f830160051c810160208410611cd9575b601f830160051c82018110611cce575050611968565b858155600101611cb8565b5080611cb8565b634e487b7160e01b83526041600452602483fd5b015190503880611924565b6001840183526020832090835b601f1984168110611d53575060019394959683601f19811610611d3a575b505050811b01600183015561193c565b015160001960f88460031b161c19169055388080611d2a565b9091602060018192858b015181550193019101611d0c565b60018401835260208320601f830160051c810160208410611da8575b601f830160051c82018110611d9d57505061190a565b848155600101611d87565b5080611d87565b0151905038806118c9565b8285526020852090855b601f1984168110611e08575060019394959683601f19811610611def575b505050811b0181556118de565b015160001960f88460031b161c19169055388080611de2565b9091602060018192858b015181550193019101611dc4565b82855260208520601f830160051c810160208410611e5a575b601f830160051c82018110611e4f5750506118af565b868155600101611e39565b5080611e39565b604051631d7eb35960e31b8152600490fd5b50303314611780565b600901546001600160a01b03163314905038611778565b50346101ea5760403660031901126101ea576020611ec7604051611eb68161269c565b600435815260243583820152612e8a565b604051908152f35b50346101ea5760c03660031901126101ea57600435611eed3661270e565b611ef5612736565b6000838152600260205260409020600401549091906001600160a01b0316156101d857602092611ec79260a4359260843592612de8565b50346101ea5760209060206003193601126101ea57611f4961262e565b6004546001600160a01b039390929091841681805b858110611fea5750611f6f90612baa565b9482805b868110611f8c5760405180611f888a82612644565b0390f35b611f9581612b4e565b9054600391821b1c835260018752848460046040862001541614611fbd575b50600101611f73565b8195611fe391611fce600194612b4e565b9054911b1c611fdd828c612bdc565b52612b85565b9490611fb4565b82611ff482612b4e565b9054600391821b1c865260018088526117f561206d60408920936117f56120426040519561202187612680565b604051612032816117f5818c6128d5565b8752604051928380928a016128d5565b8b85015260405161205a816117f58160028a016128d5565b60408501526040519283809287016128d5565b60608201526101608a600484015416928360808401528b60058201541660a0840152600681015460c0840152600781015460e0840152600a600891828101546101008601526009810154610120860152015460ff9182821615156101408601521c161515910152146120e2575b600101611f5e565b906120ee600191612b85565b9190506120da565b50346101ea5760403660031901126101ea5760048035600081815260016020526040902090910154602435906001600160a01b03161561043a57818352602092600184526040812091600683015485836121706040518381019086825284815261215f8161269c565b6040519283928392519283916125e6565b8101039060025afa1561221c5782510361220a57600a830190815460ff8160081c166104285760ff811661041657600785019190915560ff1916600117905560058201546008909201546121d892829182918291906001600160a01b03165af161016f612d7a565b7f0f7c50d316885e5d3719752f760bbbbf7d56363501e721eea4d913e255b632e482604051338152a260405160018152f35b60405163e73bcb3560e01b8152600490fd5b6040513d84823e3d90fd5b50346101ea5760c03660031901126101ea57602061226561224661262e565b61224f3661270e565b90612258612736565b60a4359260843592612cf6565b6040519015158152f35b50346101ea5760203660031901126101ea5761228c600435612bf0565b60405180916020825280516122fa6122b2610180928360208701526101a0860190612609565b6122e56122d1602086015192601f1993848983030160408a0152612609565b604086015183888303016060890152612609565b90606085015190868303016080870152612609565b91608081015160018060a01b0380911660a08601528060a08301511660c086015260c082015160e086015260e08201516101009081870152820151610120908187015282015190610140911681860152810151906101609115158286015201511515908301520390f35b50346101ea5760203660031901126101ea5760406020916004358152600383522054604051908152f35b50346101ea5760209060206003193601126101ea576123ab61262e565b9181806005936005549460018060a01b03809716925b8681106124355750506123d390612baa565b9482805b8681106123ec5760405180611f888a82612644565b6123f581612b01565b9054600391821b1c83526002875284846004604086200154161461241d575b506001016123d7565b819561242e91611fce600194612b01565b9490612414565b8361243f82612b01565b9054600391821b1c8752876117f56124af6002938484526117f561205a60408d209660016040519761247089612680565b604051612481816117f5818e6128d5565b895261249e8a61249760405180958193016128d5565b03836126ed565b880152604051928380928a016128d5565b60608201526101608b600484015416928360808401528c60098189840154169260a09384870152600681015460c0870152600781015460e087015260088101546101008701520154918291821661012086015260ff9283911c16151561014085015260a81c16151591015214612528575b6001016123c1565b91612534600191612b85565b929050612520565b50346101ea5760203660031901126101ea5761255960043561296b565b604051809160208252805161257f6122b2610180928360208701526101a0860190612609565b91608081015160018060a01b0380911660a086015260a08201511660c085015260c081015160e085015260e0810151610100908186015281015161012090818601528101516101409081860152810151906101609115158286015201511515908301520390f35b60005b8381106125f95750506000910152565b81810151838201526020016125e9565b90602091612622815180928185528580860191016125e6565b601f01601f1916010190565b600435906001600160a01b038216820361033557565b602090602060408183019282815285518094520193019160005b82811061266c575050505090565b83518552938101939281019260010161265e565b61018081019081106001600160401b0382111761031f57604052565b604081019081106001600160401b0382111761031f57604052565b602081019081106001600160401b0382111761031f57604052565b608081019081106001600160401b0382111761031f57604052565b90601f801991011681019081106001600160401b0382111761031f57604052565b604090602319011261033557604051906127278261269c565b60243582526044356020830152565b6064359060ff8216820361033557565b6001600160401b03811161031f57601f01601f191660200190565b81601f820112156103355780359061277882612746565b9261278660405194856126ed565b8284526020838301011161033557816000926020809301838601378301015290565b6001600160401b03811161031f5760051b60200190565b81601f82011215610335578035916020916127d9846127a8565b936127e760405195866126ed565b808552838086019160051b8301019280841161033557848301915b8483106128125750505050505090565b82356001600160401b03811161033557869161283384848094890101612761565b815201920191612802565b6040519061284b82612680565b816060815260606020820152606060408201526060808201526101606000918260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201520152565b90600182811c921680156128cb575b60208310146128b557565b634e487b7160e01b600052602260045260246000fd5b91607f16916128aa565b8054600093926128e48261289b565b9182825260209360019160018116908160001461294c575060011461290b575b5050505050565b90939495506000929192528360002092846000945b83861061293857505050500101903880808080612904565b805485870183015294019385908201612920565b60ff19168685015250505090151560051b010191503880808080612904565b61297361283e565b506000818152600160205260409020600401546001600160a01b031615612a71576000526001602052604060ff600a826000208351936129b285612680565b80516129c2816117f581866128d5565b855280516129d7816117f581600187016128d5565b602086015280516129ef816117f581600287016128d5565b8186015251612a05816117f581600386016128d5565b606085015260048101546001600160a01b03908116608086015260058201541660a0850152600681015460c0850152600781015460e085015260088082015461010086015260098201546101208601529101548281161515610140850152901c16151561016082015290565b506040805190612a8082612680565b805190612a8c826126b7565b60009182815283528051612a9f816126b7565b82815260208401528051612ab2816126b7565b8281528184015251612ac3816126b7565b81815260608301528060808301528060a08301528060c08301528060e083015280610100830152806101208301528061014083015261016082015290565b600554811015612b385760056000527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00190600090565b634e487b7160e01b600052603260045260246000fd5b600454811015612b385760046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0190600090565b6000198114612b945760010190565b634e487b7160e01b600052601160045260246000fd5b90612bb4826127a8565b612bc160405191826126ed565b8281528092612bd2601f19916127a8565b0190602036910137565b8051821015612b385760209160051b010190565b612bf861283e565b506000818152600260205260409020600401546001600160a01b031615612a71576000526002602052604060ff81600020825192612c3584612680565b8051612c45816117f581866128d5565b84528051612c5a816117f581600187016128d5565b60208501528051612c72816117f581600287016128d5565b8185015251612c88816117f581600386016128d5565b6060840152600960018060a01b03918260048201541660808601528260058201541660a0860152600681015460c0860152600781015460e086015260088101546101008601520154908116610120840152818160a01c16151561014084015260a81c16151561016082015290565b9360209260809160ff956000968795612d10875491612e8a565b604051908982019261190160f01b84526022830152604282015260428152612d37816126d2565b5190209360405194855216868401526040830152606082015282805260015afa15612d6e57516001600160a01b0390811691161490565b604051903d90823e3d90fd5b3d15612da5573d90612d8b82612746565b91612d9960405193846126ed565b82523d6000602084013e565b606090565b15612db157565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b939092612df6928433612cf6565b15612e785760208151910151906040519263c5bea8b560e01b84526004840152602483015260448201526020816064816000305af1908115612e6c57600091612e3d575090565b90506020813d602011612e64575b81612e58602093836126ed565b81010312610335575190565b3d9150612e4b565b6040513d6000823e3d90fd5b60405163553470cf60e01b8152600490fd5b602081519101516040519060208201927f60a3779ca56ee3eec550d74cf166571491c060455674e514bc4193adcc9e6c1384526040830152606082015260608152612ed4816126d2565b51902090565b600454600160401b81101561031f576105ce816001612efc9301600455612b4e565b9055565b600060443d10612f5d57604051600319913d83016004833e81516001600160401b03918282113d602484011117612f6057818401948551938411612f68573d85010160208487010111612f605750612f5d929101602001906126ed565b90565b949350505050565b50949350505050565b90808251908181526020809101926020808460051b8301019501936000915b848310612fa05750505050505090565b9091929394958480612fbe600193601f198682030187528a51612609565b9801930193019194939290612f9056fea2646970667358221220fba4e1ba9fcad68716e83408b3d43ba3ec07ecd56a0214cade611db99454214264736f6c63430008170033