Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Forwarder
- Optimization enabled
- true
- Compiler version
- v0.8.12+commit.f00d7308
- Optimization runs
- 300
- EVM Version
- london
- Verified at
- 2024-09-16T20:06:35.900091Z
contracts/forwarder/Forwarder.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; /// @author thirdweb // $$\ $$\ $$\ $$\ $$\ // $$ | $$ | \__| $$ | $$ | // $$$$$$\ $$$$$$$\ $$\ $$$$$$\ $$$$$$$ |$$\ $$\ $$\ $$$$$$\ $$$$$$$\ // \_$$ _| $$ __$$\ $$ |$$ __$$\ $$ __$$ |$$ | $$ | $$ |$$ __$$\ $$ __$$\ // $$ | $$ | $$ |$$ |$$ | \__|$$ / $$ |$$ | $$ | $$ |$$$$$$$$ |$$ | $$ | // $$ |$$\ $$ | $$ |$$ |$$ | $$ | $$ |$$ | $$ | $$ |$$ ____|$$ | $$ | // \$$$$ |$$ | $$ |$$ |$$ | \$$$$$$$ |\$$$$$\$$$$ |\$$$$$$$\ $$$$$$$ | // \____/ \__| \__|\__|\__| \_______| \_____\____/ \_______|\_______/ import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; /* * @dev Minimal forwarder for GSNv2 */ contract Forwarder is EIP712 { using ECDSA for bytes32; struct ForwardRequest { address from; address to; uint256 value; uint256 gas; uint256 nonce; bytes data; } bytes32 private constant TYPEHASH = keccak256("ForwardRequest(address from,address to,uint256 value,uint256 gas,uint256 nonce,bytes data)"); mapping(address => uint256) private _nonces; constructor() EIP712("GSNv2 Forwarder", "0.0.1") {} function getNonce(address from) public view returns (uint256) { return _nonces[from]; } function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool) { address signer = _hashTypedDataV4( keccak256(abi.encode(TYPEHASH, req.from, req.to, req.value, req.gas, req.nonce, keccak256(req.data))) ).recover(signature); return _nonces[req.from] == req.nonce && signer == req.from; } function execute(ForwardRequest calldata req, bytes calldata signature) public payable returns (bool, bytes memory) { require(verify(req, signature), "MinimalForwarder: signature does not match request"); _nonces[req.from] = req.nonce + 1; // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory result) = req.to.call{ gas: req.gas, value: req.value }( abi.encodePacked(req.data, req.from) ); if (!success) { // Next 5 lines from https://ethereum.stackexchange.com/a/83577 if (result.length < 68) revert("Transaction reverted silently"); assembly { result := add(result, 0x04) } revert(abi.decode(result, (string))); } // Check gas: https://ronan.eth.link/blog/ethereum-gas-dangers/ assert(gasleft() > req.gas / 63); return (success, result); } }
node_modules/@openzeppelin/contracts/utils/Strings.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @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) { 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); } } /** * @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 = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 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. * * _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 Message, created from `s`. 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(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @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)); } }
node_modules/@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
Compiler Settings
{"remappings":["@chainlink/contracts/src/=node_modules/@chainlink/contracts/src/","@ds-test/=lib/ds-test/src/","@openzeppelin/=node_modules/@openzeppelin/","@std/=lib/forge-std/src/","contracts/=contracts/","ds-test/=lib/ds-test/src/","dynamic-contracts/=lib/dynamic-contracts/src/","erc721a-upgradeable/=node_modules/erc721a-upgradeable/","erc721a/=node_modules/erc721a/","forge-std/=lib/forge-std/src/"],"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":300,"enabled":true},"libraries":{},"evmVersion":"london"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"bool","name":"","internalType":"bool"},{"type":"bytes","name":"","internalType":"bytes"}],"name":"execute","inputs":[{"type":"tuple","name":"req","internalType":"struct Forwarder.ForwardRequest","components":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"gas","internalType":"uint256"},{"type":"uint256","name":"nonce","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"bytes","name":"signature","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getNonce","inputs":[{"type":"address","name":"from","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"verify","inputs":[{"type":"tuple","name":"req","internalType":"struct Forwarder.ForwardRequest","components":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"gas","internalType":"uint256"},{"type":"uint256","name":"nonce","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"bytes","name":"signature","internalType":"bytes"}]}]
Contract Creation Code
0x61014060405234801561001157600080fd5b50604080518082018252600f81526e23a9a73b19102337b93bb0b93232b960891b602080830191825283518085019094526005845264302e302e3160d81b908401528151902060e08190527fae209a0b48f21c054280f2455d32cf309387644879d9acbd8ffc1991638118856101008190524660a0529192917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6100fa8184846040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6080523060c052610120525061010f92505050565b60805160a05160c05160e0516101005161012051610c7061015e600039600061057b015260006105ca015260006105a5015260006104fe01526000610528015260006105520152610c706000f3fe6080604052600436106100345760003560e01c80632d0335ab1461003957806347153f8214610082578063bf5d3bdb146100a3575b600080fd5b34801561004557600080fd5b5061006f610054366004610909565b6001600160a01b031660009081526020819052604090205490565b6040519081526020015b60405180910390f35b610095610090366004610939565b6100d3565b604051610079929190610a34565b3480156100af57600080fd5b506100c36100be366004610939565b6102fb565b6040519015158152602001610079565b600060606100e28585856102fb565b61014e5760405162461bcd60e51b815260206004820152603260248201527f4d696e696d616c466f727761726465723a207369676e617475726520646f6573604482015271081b9bdd081b585d18da081c995c5d595cdd60721b60648201526084015b60405180910390fd5b61015d60808601356001610a57565b60008061016d6020890189610909565b6001600160a01b03166001600160a01b03168152602001908152602001600020819055506000808660200160208101906101a79190610909565b6001600160a01b0316606088013560408901356101c760a08b018b610a7d565b6101d460208d018d610909565b6040516020016101e693929190610ac4565b60408051601f198184030181529082905261020091610aea565b600060405180830381858888f193505050503d806000811461023e576040519150601f19603f3d011682016040523d82523d6000602084013e610243565b606091505b5091509150816102d25760448151101561029f5760405162461bcd60e51b815260206004820152601d60248201527f5472616e73616374696f6e2072657665727465642073696c656e746c790000006044820152606401610145565b600481019050808060200190518101906102b99190610b1c565b60405162461bcd60e51b81526004016101459190610bc9565b6102e1603f6060890135610bdc565b5a116102ef576102ef610bfe565b90969095509350505050565b60008061040e84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061040892507fdd8f4b70b0f4393e889bd39128a30628a78b61816a9eb8199759e7a349657e48915061036b905060208a018a610909565b61037b60408b0160208c01610909565b60408b013560608c013560808d013561039760a08f018f610a7d565b6040516103a5929190610c14565b6040805191829003822060208301989098526001600160a01b0396871690820152949093166060850152608084019190915260a083015260c082015260e08101919091526101000160405160208183030381529060405280519060200120610479565b906104cd565b905060808501356000806104256020890189610909565b6001600160a01b03166001600160a01b0316815260200190815260200160002054148015610470575061045b6020860186610909565b6001600160a01b0316816001600160a01b0316145b95945050505050565b60006104c76104866104f1565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b92915050565b60008060006104dc8585610618565b915091506104e98161065e565b509392505050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561054a57507f000000000000000000000000000000000000000000000000000000000000000046145b1561057457507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60008082516041141561064f5760208301516040840151606085015160001a6106438782858561081c565b94509450505050610657565b506000905060025b9250929050565b600081600481111561067257610672610c24565b141561067b5750565b600181600481111561068f5761068f610c24565b14156106dd5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610145565b60028160048111156106f1576106f1610c24565b141561073f5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610145565b600381600481111561075357610753610c24565b14156107ac5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610145565b60048160048111156107c0576107c0610c24565b14156108195760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610145565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156108535750600090506003610900565b8460ff16601b1415801561086b57508460ff16601c14155b1561087c5750600090506004610900565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156108d0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166108f957600060019250925050610900565b9150600090505b94509492505050565b60006020828403121561091b57600080fd5b81356001600160a01b038116811461093257600080fd5b9392505050565b60008060006040848603121561094e57600080fd5b833567ffffffffffffffff8082111561096657600080fd5b9085019060c0828803121561097a57600080fd5b9093506020850135908082111561099057600080fd5b818601915086601f8301126109a457600080fd5b8135818111156109b357600080fd5b8760208285010111156109c557600080fd5b6020830194508093505050509250925092565b60005b838110156109f35781810151838201526020016109db565b83811115610a02576000848401525b50505050565b60008151808452610a208160208601602086016109d8565b601f01601f19169290920160200192915050565b8215158152604060208201526000610a4f6040830184610a08565b949350505050565b60008219821115610a7857634e487b7160e01b600052601160045260246000fd5b500190565b6000808335601e19843603018112610a9457600080fd5b83018035915067ffffffffffffffff821115610aaf57600080fd5b60200191503681900382131561065757600080fd5b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008251610afc8184602087016109d8565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610b2e57600080fd5b815167ffffffffffffffff80821115610b4657600080fd5b818401915084601f830112610b5a57600080fd5b815181811115610b6c57610b6c610b06565b604051601f8201601f19908116603f01168101908382118183101715610b9457610b94610b06565b81604052828152876020848701011115610bad57600080fd5b610bbe8360208301602088016109d8565b979650505050505050565b6020815260006109326020830184610a08565b600082610bf957634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052600160045260246000fd5b8183823760009101908152919050565b634e487b7160e01b600052602160045260246000fdfea264697066735822122020e883c2c1f520876ac5e0646e730725ffcab01ff8d7c2a3c0684cfacb64528b64736f6c634300080c0033
Deployed ByteCode
0x6080604052600436106100345760003560e01c80632d0335ab1461003957806347153f8214610082578063bf5d3bdb146100a3575b600080fd5b34801561004557600080fd5b5061006f610054366004610909565b6001600160a01b031660009081526020819052604090205490565b6040519081526020015b60405180910390f35b610095610090366004610939565b6100d3565b604051610079929190610a34565b3480156100af57600080fd5b506100c36100be366004610939565b6102fb565b6040519015158152602001610079565b600060606100e28585856102fb565b61014e5760405162461bcd60e51b815260206004820152603260248201527f4d696e696d616c466f727761726465723a207369676e617475726520646f6573604482015271081b9bdd081b585d18da081c995c5d595cdd60721b60648201526084015b60405180910390fd5b61015d60808601356001610a57565b60008061016d6020890189610909565b6001600160a01b03166001600160a01b03168152602001908152602001600020819055506000808660200160208101906101a79190610909565b6001600160a01b0316606088013560408901356101c760a08b018b610a7d565b6101d460208d018d610909565b6040516020016101e693929190610ac4565b60408051601f198184030181529082905261020091610aea565b600060405180830381858888f193505050503d806000811461023e576040519150601f19603f3d011682016040523d82523d6000602084013e610243565b606091505b5091509150816102d25760448151101561029f5760405162461bcd60e51b815260206004820152601d60248201527f5472616e73616374696f6e2072657665727465642073696c656e746c790000006044820152606401610145565b600481019050808060200190518101906102b99190610b1c565b60405162461bcd60e51b81526004016101459190610bc9565b6102e1603f6060890135610bdc565b5a116102ef576102ef610bfe565b90969095509350505050565b60008061040e84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061040892507fdd8f4b70b0f4393e889bd39128a30628a78b61816a9eb8199759e7a349657e48915061036b905060208a018a610909565b61037b60408b0160208c01610909565b60408b013560608c013560808d013561039760a08f018f610a7d565b6040516103a5929190610c14565b6040805191829003822060208301989098526001600160a01b0396871690820152949093166060850152608084019190915260a083015260c082015260e08101919091526101000160405160208183030381529060405280519060200120610479565b906104cd565b905060808501356000806104256020890189610909565b6001600160a01b03166001600160a01b0316815260200190815260200160002054148015610470575061045b6020860186610909565b6001600160a01b0316816001600160a01b0316145b95945050505050565b60006104c76104866104f1565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b92915050565b60008060006104dc8585610618565b915091506104e98161065e565b509392505050565b6000306001600160a01b037f0000000000000000000000004413b15503b560d79e28911683b0c679968e2c751614801561054a57507f000000000000000000000000000000000000000000000000000000000000142d46145b1561057457507fc89239f1001ce303199efc486e1b69b0b88bcd3a5e4710ee86d01d94ee16e36590565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f2c9c579ca0d993f7c2d25818372353ab1d6abb72d19f803687d19c75043ce92a828401527fae209a0b48f21c054280f2455d32cf309387644879d9acbd8ffc19916381188560608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60008082516041141561064f5760208301516040840151606085015160001a6106438782858561081c565b94509450505050610657565b506000905060025b9250929050565b600081600481111561067257610672610c24565b141561067b5750565b600181600481111561068f5761068f610c24565b14156106dd5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610145565b60028160048111156106f1576106f1610c24565b141561073f5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610145565b600381600481111561075357610753610c24565b14156107ac5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610145565b60048160048111156107c0576107c0610c24565b14156108195760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610145565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156108535750600090506003610900565b8460ff16601b1415801561086b57508460ff16601c14155b1561087c5750600090506004610900565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156108d0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166108f957600060019250925050610900565b9150600090505b94509492505050565b60006020828403121561091b57600080fd5b81356001600160a01b038116811461093257600080fd5b9392505050565b60008060006040848603121561094e57600080fd5b833567ffffffffffffffff8082111561096657600080fd5b9085019060c0828803121561097a57600080fd5b9093506020850135908082111561099057600080fd5b818601915086601f8301126109a457600080fd5b8135818111156109b357600080fd5b8760208285010111156109c557600080fd5b6020830194508093505050509250925092565b60005b838110156109f35781810151838201526020016109db565b83811115610a02576000848401525b50505050565b60008151808452610a208160208601602086016109d8565b601f01601f19169290920160200192915050565b8215158152604060208201526000610a4f6040830184610a08565b949350505050565b60008219821115610a7857634e487b7160e01b600052601160045260246000fd5b500190565b6000808335601e19843603018112610a9457600080fd5b83018035915067ffffffffffffffff821115610aaf57600080fd5b60200191503681900382131561065757600080fd5b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008251610afc8184602087016109d8565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610b2e57600080fd5b815167ffffffffffffffff80821115610b4657600080fd5b818401915084601f830112610b5a57600080fd5b815181811115610b6c57610b6c610b06565b604051601f8201601f19908116603f01168101908382118183101715610b9457610b94610b06565b81604052828152876020848701011115610bad57600080fd5b610bbe8360208301602088016109d8565b979650505050505050565b6020815260006109326020830184610a08565b600082610bf957634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052600160045260246000fd5b8183823760009101908152919050565b634e487b7160e01b600052602160045260246000fdfea264697066735822122020e883c2c1f520876ac5e0646e730725ffcab01ff8d7c2a3c0684cfacb64528b64736f6c634300080c0033