Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- SafeToL2Migration
- Optimization enabled
- false
- Compiler version
- v0.7.6+commit.7338295f
- EVM Version
- default
- Verified at
- 2024-05-20T14:35:53.676651Z
contracts/libraries/SafeToL2Migration.sol
// SPDX-License-Identifier: LGPL-3.0-only /* solhint-disable one-contract-per-file */ pragma solidity >=0.7.0 <0.9.0; import {SafeStorage} from "../libraries/SafeStorage.sol"; import {Enum} from "../libraries/Enum.sol"; import {ISafe} from "../interfaces/ISafe.sol"; /** * @title Migration Contract for updating a Safe from 1.1.1/1.3.0/1.4.1 versions to a L2 version. Useful when replaying a Safe from a non L2 network in a L2 network. * @notice This contract facilitates the migration of a Safe contract from version 1.1.1 to 1.3.0/1.4.1 L2, 1.3.0 to 1.3.0L2 or from 1.4.1 to 1.4.1L2 * Other versions are not supported * @dev IMPORTANT: The migration will only work with proxies that store the implementation address in the storage slot 0. */ contract SafeToL2Migration is SafeStorage { // Address of this contract address public immutable MIGRATION_SINGLETON; /** * @notice Constructor * @dev Initializes the migrationSingleton with the contract's own address. */ constructor() { MIGRATION_SINGLETON = address(this); } /** * @notice Event indicating a change of master copy address. * @param singleton New master copy address */ event ChangedMasterCopy(address singleton); event SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler); event SafeMultiSigTransaction( address to, uint256 value, bytes data, Enum.Operation operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address payable refundReceiver, bytes signatures, // We combine nonce, sender and threshold into one to avoid stack too deep // Dev note: additionalInfo should not contain `bytes`, as this complicates decoding bytes additionalInfo ); /** * @notice Modifier to make a function callable via delegatecall only. * If the function is called via a regular call, it will revert. */ modifier onlyDelegateCall() { require(address(this) != MIGRATION_SINGLETON, "Migration should only be called via delegatecall"); _; } /** * @notice Modifier to prevent using initialized Safes. * If Safe has a nonce higher than 0, it will revert */ modifier onlyNonceZero() { // Nonce is increased before executing a tx, so first executed tx will have nonce=1 require(nonce == 1, "Safe must have not executed any tx"); _; } /** * @dev Internal function with common migration steps, changes the singleton and emits SafeMultiSigTransaction event */ function migrate(address l2Singleton, bytes memory functionData) private { singleton = l2Singleton; // Encode nonce, sender, threshold bytes memory additionalInfo = abi.encode(0, msg.sender, threshold); // Simulate a L2 transaction so Safe Tx Service indexer picks up the Safe emit SafeMultiSigTransaction( MIGRATION_SINGLETON, 0, functionData, Enum.Operation.DelegateCall, 0, 0, 0, address(0), payable(address(0)), "", // We cannot detect signatures additionalInfo ); emit ChangedMasterCopy(singleton); } /** * @notice Migrate from Safe 1.3.0/1.4.1 Singleton (L1) to the same version provided L2 singleton * Safe is required to have nonce 0 so backend can support it after the migration * @dev This function should only be called via a delegatecall to perform the upgrade. * Singletons versions will be compared, so it implies that contracts exist */ function migrateToL2(address l2Singleton) public onlyDelegateCall onlyNonceZero { require(address(singleton) != l2Singleton, "Safe is already using the singleton"); bytes32 oldSingletonVersion = keccak256(abi.encodePacked(ISafe(singleton).VERSION())); bytes32 newSingletonVersion = keccak256(abi.encodePacked(ISafe(l2Singleton).VERSION())); require(oldSingletonVersion == newSingletonVersion, "L2 singleton must match current version singleton"); // There's no way to make sure if address is a valid singleton, unless we configure the contract for every chain require( newSingletonVersion == keccak256(abi.encodePacked("1.3.0")) || newSingletonVersion == keccak256(abi.encodePacked("1.4.1")), "Provided singleton version is not supported" ); // 0xef2624ae - keccak("migrateToL2(address)") bytes memory functionData = abi.encodeWithSelector(0xef2624ae, l2Singleton); migrate(l2Singleton, functionData); } /** * @notice Migrate from Safe 1.1.1 Singleton to 1.3.0 or 1.4.1 L2 * Safe is required to have nonce 0 so backend can support it after the migration * @dev This function should only be called via a delegatecall to perform the upgrade. * Singletons version will be checked, so it implies that contracts exist. * A valid and compatible fallbackHandler needs to be provided, only existance will be checked. */ function migrateFromV111(address l2Singleton, address fallbackHandler) public onlyDelegateCall onlyNonceZero { require(isContract(fallbackHandler), "fallbackHandler is not a contract"); bytes32 oldSingletonVersion = keccak256(abi.encodePacked(ISafe(singleton).VERSION())); require(oldSingletonVersion == keccak256(abi.encodePacked("1.1.1")), "Provided singleton version is not supported"); bytes32 newSingletonVersion = keccak256(abi.encodePacked(ISafe(l2Singleton).VERSION())); require( newSingletonVersion == keccak256(abi.encodePacked("1.3.0")) || newSingletonVersion == keccak256(abi.encodePacked("1.4.1")), "Provided singleton version is not supported" ); ISafe safe = ISafe(address(this)); safe.setFallbackHandler(fallbackHandler); // Safes < 1.3.0 did not emit SafeSetup, so Safe Tx Service backend needs the event to index the Safe emit SafeSetup(MIGRATION_SINGLETON, safe.getOwners(), safe.getThreshold(), address(0), fallbackHandler); // 0xd9a20812 - keccak("migrateFromV111(address,address)") bytes memory functionData = abi.encodeWithSelector(0xd9a20812, l2Singleton, fallbackHandler); migrate(l2Singleton, functionData); } /** * @notice Checks whether an Ethereum address corresponds to a contract or an externally owned account (EOA). * @param account The Ethereum address to be checked. * @return A boolean value indicating whether the address is associated with a contract (true) or an EOA (false). * @dev This function relies on the `extcodesize` assembly opcode to determine whether an address is a contract. * It may return incorrect results in some edge cases (see documentation for details). * Developers should use caution when relying on the results of this function for critical decision-making. */ function isContract(address account) internal view returns (bool) { uint256 size; /* solhint-disable no-inline-assembly */ /// @solidity memory-safe-assembly assembly { size := extcodesize(account) } /* solhint-enable no-inline-assembly */ // If the code size is greater than 0, it is a contract; otherwise, it is an EOA. return size > 0; } }
contracts/interfaces/IOwnerManager.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title IOwnerManager - Interface for contract which manages Safe owners and a threshold to authorize transactions. * @author @safe-global/safe-protocol */ interface IOwnerManager { event AddedOwner(address indexed owner); event RemovedOwner(address indexed owner); event ChangedThreshold(uint256 threshold); /** * @notice Adds the owner `owner` to the Safe and updates the threshold to `_threshold`. * @dev This can only be done via a Safe transaction. * @param owner New owner address. * @param _threshold New threshold. */ function addOwnerWithThreshold(address owner, uint256 _threshold) external; /** * @notice Removes the owner `owner` from the Safe and updates the threshold to `_threshold`. * @dev This can only be done via a Safe transaction. * @param prevOwner Owner that pointed to the owner to be removed in the linked list * @param owner Owner address to be removed. * @param _threshold New threshold. */ function removeOwner(address prevOwner, address owner, uint256 _threshold) external; /** * @notice Replaces the owner `oldOwner` in the Safe with `newOwner`. * @dev This can only be done via a Safe transaction. * @param prevOwner Owner that pointed to the owner to be replaced in the linked list * @param oldOwner Owner address to be replaced. * @param newOwner New owner address. */ function swapOwner(address prevOwner, address oldOwner, address newOwner) external; /** * @notice Changes the threshold of the Safe to `_threshold`. * @dev This can only be done via a Safe transaction. * @param _threshold New threshold. */ function changeThreshold(uint256 _threshold) external; /** * @notice Returns the number of required confirmations for a Safe transaction aka the threshold. * @return Threshold number. */ function getThreshold() external view returns (uint256); /** * @notice Returns if `owner` is an owner of the Safe. * @return Boolean if owner is an owner of the Safe. */ function isOwner(address owner) external view returns (bool); /** * @notice Returns a list of Safe owners. * @return Array of Safe owners. */ function getOwners() external view returns (address[] memory); }
contracts/interfaces/ISafe.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import {Enum} from "../libraries/Enum.sol"; import {IModuleManager} from "./IModuleManager.sol"; import {IOwnerManager} from "./IOwnerManager.sol"; import {IFallbackManager} from "./IFallbackManager.sol"; /** * @title ISafe - A multisignature wallet interface with support for confirmations using signed messages based on EIP-712. * @author @safe-global/safe-protocol */ interface ISafe is IModuleManager, IOwnerManager, IFallbackManager { event SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler); event ApproveHash(bytes32 indexed approvedHash, address indexed owner); event SignMsg(bytes32 indexed msgHash); event ExecutionFailure(bytes32 indexed txHash, uint256 payment); event ExecutionSuccess(bytes32 indexed txHash, uint256 payment); /** * @notice Sets an initial storage of the Safe contract. * @dev This method can only be called once. * If a proxy was created without setting up, anyone can call setup and claim the proxy. * @param _owners List of Safe owners. * @param _threshold Number of required confirmations for a Safe transaction. * @param to Contract address for optional delegate call. * @param data Data payload for optional delegate call. * @param fallbackHandler Handler for fallback calls to this contract * @param paymentToken Token that should be used for the payment (0 is ETH) * @param payment Value that should be paid * @param paymentReceiver Address that should receive the payment (or 0 if tx.origin) */ function setup( address[] calldata _owners, uint256 _threshold, address to, bytes calldata data, address fallbackHandler, address paymentToken, uint256 payment, address payable paymentReceiver ) external; /** @notice Executes a `operation` {0: Call, 1: DelegateCall}} transaction to `to` with `value` (Native Currency) * and pays `gasPrice` * `gasLimit` in `gasToken` token to `refundReceiver`. * @dev The fees are always transferred, even if the user transaction fails. * This method doesn't perform any sanity check of the transaction, such as: * - if the contract at `to` address has code or not * - if the `gasToken` is a contract or not * It is the responsibility of the caller to perform such checks. * @param to Destination address of Safe transaction. * @param value Ether value of Safe transaction. * @param data Data payload of Safe transaction. * @param operation Operation type of Safe transaction. * @param safeTxGas Gas that should be used for the Safe transaction. * @param baseGas Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund) * @param gasPrice Gas price that should be used for the payment calculation. * @param gasToken Token address (or 0 if ETH) that is used for the payment. * @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin). * @param signatures Signature data that should be verified. * Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash. * @return success Boolean indicating transaction's success. */ function execTransaction( address to, uint256 value, bytes calldata data, Enum.Operation operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address payable refundReceiver, bytes memory signatures ) external payable returns (bool success); /** * @notice Checks whether the signature provided is valid for the provided data and hash. Reverts otherwise. * @param dataHash Hash of the data (could be either a message hash or transaction hash) * @param signatures Signature data that should be verified. * Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash. */ function checkSignatures(bytes32 dataHash, bytes memory signatures) external view; /** * @notice Checks whether the signature provided is valid for the provided data and hash. Reverts otherwise. * @param dataHash Hash of the data (could be either a message hash or transaction hash) * @param signatures Signature data that should be verified. * Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash. * @dev This function makes it compatible with previous versions. */ function checkSignatures(bytes32 dataHash, bytes memory /* IGNORED */, bytes memory signatures) external view; /** * @notice Checks whether the signature provided is valid for the provided data and hash. Reverts otherwise. * @dev Since the EIP-1271 does an external call, be mindful of reentrancy attacks. * @param executor Address that executing the transaction. * ⚠️⚠️⚠️ Make sure that the executor address is a legitmate executor. * Incorrectly passed the executor might reduce the threshold by 1 signature. ⚠️⚠️⚠️ * @param dataHash Hash of the data (could be either a message hash or transaction hash) * @param signatures Signature data that should be verified. * Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash. * @param requiredSignatures Amount of required valid signatures. */ function checkNSignatures(address executor, bytes32 dataHash, bytes memory signatures, uint256 requiredSignatures) external view; /** * @notice Marks hash `hashToApprove` as approved. * @dev This can be used with a pre-approved hash transaction signature. * IMPORTANT: The approved hash stays approved forever. There's no revocation mechanism, so it behaves similarly to ECDSA signatures * @param hashToApprove The hash to mark as approved for signatures that are verified by this contract. */ function approveHash(bytes32 hashToApprove) external; /** * @dev Returns the domain separator for this contract, as defined in the EIP-712 standard. * @return bytes32 The domain separator hash. */ function domainSeparator() external view returns (bytes32); /** * @notice Returns transaction hash to be signed by owners. * @param to Destination address. * @param value Ether value. * @param data Data payload. * @param operation Operation type. * @param safeTxGas Gas that should be used for the safe transaction. * @param baseGas Gas costs for data used to trigger the safe transaction. * @param gasPrice Maximum gas price that should be used for this transaction. * @param gasToken Token address (or 0 if ETH) that is used for the payment. * @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin). * @param _nonce Transaction nonce. * @return Transaction hash. */ function getTransactionHash( address to, uint256 value, bytes calldata data, Enum.Operation operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address refundReceiver, uint256 _nonce ) external view returns (bytes32); /** * External getter function for state variables. */ /** * @notice Returns the version of the Safe contract. * @return Version string. */ // solhint-disable-next-line function VERSION() external view returns (string memory); /** * @notice Returns the nonce of the Safe contract. * @return Nonce. */ function nonce() external view returns (uint256); /** * @notice Returns a uint if the messageHash is signed by the owner. * @param messageHash Hash of message that should be checked. * @return Number denoting if an owner signed the hash. */ function signedMessages(bytes32 messageHash) external view returns (uint256); /** * @notice Returns a uint if the messageHash is approved by the owner. * @param owner Owner address that should be checked. * @param messageHash Hash of message that should be checked. * @return Number denoting if an owner approved the hash. */ function approvedHashes(address owner, bytes32 messageHash) external view returns (uint256); }
contracts/libraries/Enum.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title Enum - Collection of enums used in Safe Smart Account contracts. * @author @safe-global/safe-protocol */ library Enum { enum Operation { Call, DelegateCall } }
contracts/interfaces/IFallbackManager.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title IFallbackManager - A contract interface managing fallback calls made to this contract. * @author @safe-global/safe-protocol */ interface IFallbackManager { event ChangedFallbackHandler(address indexed handler); /** * @notice Set Fallback Handler to `handler` for the Safe. * @dev Only fallback calls without value and with data will be forwarded. * This can only be done via a Safe transaction. * Cannot be set to the Safe itself. * @param handler contract to handle fallback calls. */ function setFallbackHandler(address handler) external; }
contracts/interfaces/IGuardManager.sol
// SPDX-License-Identifier: LGPL-3.0-only /* solhint-disable one-contract-per-file */ pragma solidity >=0.7.0 <0.9.0; /** * @title IGuardManager - A contract interface managing transaction guards which perform pre and post-checks on Safe transactions. * @author @safe-global/safe-protocol */ interface IGuardManager { event ChangedGuard(address indexed guard); /** * @dev Set a guard that checks transactions before execution * This can only be done via a Safe transaction. * ⚠️ IMPORTANT: Since a guard has full power to block Safe transaction execution, * a broken guard can cause a denial of service for the Safe. Make sure to carefully * audit the guard code and design recovery mechanisms. * @notice Set Transaction Guard `guard` for the Safe. Make sure you trust the guard. * @param guard The address of the guard to be used or the 0 address to disable the guard */ function setGuard(address guard) external; }
contracts/interfaces/IModuleManager.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import {Enum} from "../libraries/Enum.sol"; import {IGuardManager} from "./IGuardManager.sol"; /** * @title IModuleManager - An interface of contract managing Safe modules * @notice Modules are extensions with unlimited access to a Safe that can be added to a Safe by its owners. ⚠️ WARNING: Modules are a security risk since they can execute arbitrary transactions, so only trusted and audited modules should be added to a Safe. A malicious module can completely takeover a Safe. * @author @safe-global/safe-protocol */ interface IModuleManager is IGuardManager { event EnabledModule(address indexed module); event DisabledModule(address indexed module); event ExecutionFromModuleSuccess(address indexed module); event ExecutionFromModuleFailure(address indexed module); /** * @notice Enables the module `module` for the Safe. * @dev This can only be done via a Safe transaction. * @param module Module to be whitelisted. */ function enableModule(address module) external; /** * @notice Disables the module `module` for the Safe. * @dev This can only be done via a Safe transaction. * @param prevModule Previous module in the modules linked list. * @param module Module to be removed. */ function disableModule(address prevModule, address module) external; /** * @notice Execute `operation` (0: Call, 1: DelegateCall) to `to` with `value` (Native Token) * @dev Function is virtual to allow overriding for L2 singleton to emit an event for indexing. * @param to Destination address of module transaction. * @param value Ether value of module transaction. * @param data Data payload of module transaction. * @param operation Operation type of module transaction. * @return success Boolean flag indicating if the call succeeded. */ function execTransactionFromModule( address to, uint256 value, bytes memory data, Enum.Operation operation ) external returns (bool success); /** * @notice Execute `operation` (0: Call, 1: DelegateCall) to `to` with `value` (Native Token) and return data * @param to Destination address of module transaction. * @param value Ether value of module transaction. * @param data Data payload of module transaction. * @param operation Operation type of module transaction. * @return success Boolean flag indicating if the call succeeded. * @return returnData Data returned by the call. */ function execTransactionFromModuleReturnData( address to, uint256 value, bytes memory data, Enum.Operation operation ) external returns (bool success, bytes memory returnData); /** * @notice Returns if an module is enabled * @return True if the module is enabled */ function isModuleEnabled(address module) external view returns (bool); /** * @notice Returns an array of modules. * If all entries fit into a single page, the next pointer will be 0x1. * If another page is present, next will be the last element of the returned array. * @param start Start of the page. Has to be a module or start pointer (0x1 address) * @param pageSize Maximum number of modules that should be returned. Has to be > 0 * @return array Array of modules. * @return next Start of the next page. */ function getModulesPaginated(address start, uint256 pageSize) external view returns (address[] memory array, address next); }
contracts/libraries/SafeStorage.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title SafeStorage - Storage layout of the Safe Smart Account contracts to be used in libraries. * @dev Should be always the first base contract of a library that is used with a Safe. * @author Richard Meissner - @rmeissner */ contract SafeStorage { // From /common/Singleton.sol address internal singleton; // From /common/ModuleManager.sol mapping(address => address) internal modules; // From /common/OwnerManager.sol mapping(address => address) internal owners; uint256 internal ownerCount; uint256 internal threshold; // From /Safe.sol uint256 internal nonce; bytes32 internal _deprecatedDomainSeparator; mapping(bytes32 => uint256) internal signedMessages; mapping(address => mapping(bytes32 => uint256)) internal approvedHashes; }
Compiler Settings
{"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":false},"metadata":{"useLiteralContent":true},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"ChangedMasterCopy","inputs":[{"type":"address","name":"singleton","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"SafeMultiSigTransaction","inputs":[{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"bytes","name":"data","internalType":"bytes","indexed":false},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation","indexed":false},{"type":"uint256","name":"safeTxGas","internalType":"uint256","indexed":false},{"type":"uint256","name":"baseGas","internalType":"uint256","indexed":false},{"type":"uint256","name":"gasPrice","internalType":"uint256","indexed":false},{"type":"address","name":"gasToken","internalType":"address","indexed":false},{"type":"address","name":"refundReceiver","internalType":"address payable","indexed":false},{"type":"bytes","name":"signatures","internalType":"bytes","indexed":false},{"type":"bytes","name":"additionalInfo","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"SafeSetup","inputs":[{"type":"address","name":"initiator","internalType":"address","indexed":true},{"type":"address[]","name":"owners","internalType":"address[]","indexed":false},{"type":"uint256","name":"threshold","internalType":"uint256","indexed":false},{"type":"address","name":"initializer","internalType":"address","indexed":false},{"type":"address","name":"fallbackHandler","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"MIGRATION_SINGLETON","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"migrateFromV111","inputs":[{"type":"address","name":"l2Singleton","internalType":"address"},{"type":"address","name":"fallbackHandler","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"migrateToL2","inputs":[{"type":"address","name":"l2Singleton","internalType":"address"}]}]
Contract Creation Code
0x60a060405234801561001057600080fd5b503073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b8152505060805160601c61166861007960003980610124528061014852806108415280610b70528061132552506116686000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806372f7a95614610046578063d9a208121461007a578063ef2624ae146100de575b600080fd5b61004e610122565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100dc6004803603604081101561009057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610146565b005b610120600480360360208110156100f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b6e565b005b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614156101eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001806115646030913960400191505060405180910390fd5b600160055414610246576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806116116022913960400191505060405180910390fd5b61024f81611263565b6102a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806115946021913960400191505060405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b815260040160006040518083038186803b15801561030d57600080fd5b505afa158015610321573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561034b57600080fd5b810190808051604051939291908464010000000082111561036b57600080fd5b8382019150602082018581111561038157600080fd5b825186600182028301116401000000008211171561039e57600080fd5b8083526020830192505050908051906020019080838360005b838110156103d25780820151818401526020810190506103b7565b50505050905090810190601f1680156103ff5780820380516001836020036101000a031916815260200191505b506040525050506040516020018082805190602001908083835b6020831061043c5780518252602082019150602081019050602083039250610419565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405160200180807f312e312e310000000000000000000000000000000000000000000000000000008152506005019050604051602081830303815290604052805190602001208114610517576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806115b5602b913960400191505060405180910390fd5b60008373ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b815260040160006040518083038186803b15801561055f57600080fd5b505afa158015610573573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561059d57600080fd5b81019080805160405193929190846401000000008211156105bd57600080fd5b838201915060208201858111156105d357600080fd5b82518660018202830111640100000000821117156105f057600080fd5b8083526020830192505050908051906020019080838360005b83811015610624578082015181840152602081019050610609565b50505050905090810190601f1680156106515780820380516001836020036101000a031916815260200191505b506040525050506040516020018082805190602001908083835b6020831061068e578051825260208201915060208101905060208303925061066b565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405160200180807f312e332e30000000000000000000000000000000000000000000000000000000815250600501905060405160208183030381529060405280519060200120811480610764575060405160200180807f312e342e3100000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040528051906020012081145b6107b9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806115b5602b913960400191505060405180910390fd5b60003090508073ffffffffffffffffffffffffffffffffffffffff1663f08a0323856040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b15801561082757600080fd5b505af115801561083b573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88273ffffffffffffffffffffffffffffffffffffffff1663a0e67e2b6040518163ffffffff1660e01b815260040160006040518083038186803b1580156108dd57600080fd5b505afa1580156108f1573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561091b57600080fd5b810190808051604051939291908464010000000082111561093b57600080fd5b8382019150602082018581111561095157600080fd5b825186602082028301116401000000008211171561096e57600080fd5b8083526020830192505050908051906020019060200280838360005b838110156109a557808201518184015260208101905061098a565b505050509050016040525050508373ffffffffffffffffffffffffffffffffffffffff1663e75235b86040518163ffffffff1660e01b815260040160206040518083038186803b1580156109f857600080fd5b505afa158015610a0c573d6000803e3d6000fd5b505050506040513d6020811015610a2257600080fd5b810190808051906020019092919050505060008860405180806020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828103825286818151815260200191508051906020019060200280838360005b83811015610ab7578082015181840152602081019050610a9c565b505050509050019550505050505060405180910390a2600063d9a208128686604051602401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff168152602001925050506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050610b668682611276565b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161415610c13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001806115646030913960400191505060405180910390fd5b600160055414610c6e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806116116022913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610d13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806115416023913960400191505060405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b815260040160006040518083038186803b158015610d7c57600080fd5b505afa158015610d90573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506020811015610dba57600080fd5b8101908080516040519392919084640100000000821115610dda57600080fd5b83820191506020820185811115610df057600080fd5b8251866001820283011164010000000082111715610e0d57600080fd5b8083526020830192505050908051906020019080838360005b83811015610e41578082015181840152602081019050610e26565b50505050905090810190601f168015610e6e5780820380516001836020036101000a031916815260200191505b506040525050506040516020018082805190602001908083835b60208310610eab5780518252602082019150602081019050602083039250610e88565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060008273ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b815260040160006040518083038186803b158015610f3057600080fd5b505afa158015610f44573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506020811015610f6e57600080fd5b8101908080516040519392919084640100000000821115610f8e57600080fd5b83820191506020820185811115610fa457600080fd5b8251866001820283011164010000000082111715610fc157600080fd5b8083526020830192505050908051906020019080838360005b83811015610ff5578082015181840152602081019050610fda565b50505050905090810190601f1680156110225780820380516001836020036101000a031916815260200191505b506040525050506040516020018082805190602001908083835b6020831061105f578051825260208201915060208101905060208303925061103c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012090508082146110f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001806115e06031913960400191505060405180910390fd5b60405160200180807f312e332e3000000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040528051906020012081148061118d575060405160200180807f312e342e3100000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040528051906020012081145b6111e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806115b5602b913960400191505060405180910390fd5b600063ef2624ae84604051602401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905061125d8482611276565b50505050565b600080823b905060008111915050919050565b816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008033600454604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405160208183030381529060405290507f66753cd2356569ee081232e3be8909b950e0a76c1f8460c3a5e3c2be32b11bed7f0000000000000000000000000000000000000000000000000000000000000000600084600160008060008060008a604051808b73ffffffffffffffffffffffffffffffffffffffff1681526020018a81526020018060200189600181111561138857fe5b81526020018881526020018781526020018681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff168152602001806020018060200184810384528c818151815260200191508051906020019080838360005b838110156114175780820151818401526020810190506113fc565b50505050905090810190601f1680156114445780820380516001836020036101000a031916815260200191505b50848103835260008152602001848103825285818151815260200191508051906020019080838360005b8381101561148957808201518184015260208101905061146e565b50505050905090810190601f1680156114b65780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a17f75e41bc35ff1bf14d81d1d2f649c0084a0f974f9289c803ec9898eeec4c8d0b860008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505056fe5361666520697320616c7265616479207573696e67207468652073696e676c65746f6e4d6967726174696f6e2073686f756c64206f6e6c792062652063616c6c6564207669612064656c656761746563616c6c66616c6c6261636b48616e646c6572206973206e6f74206120636f6e747261637450726f76696465642073696e676c65746f6e2076657273696f6e206973206e6f7420737570706f727465644c322073696e676c65746f6e206d757374206d617463682063757272656e742076657273696f6e2073696e676c65746f6e53616665206d7573742068617665206e6f7420657865637574656420616e79207478a26469706673582212209e7602ff6f93f41fd0d07e9f6af190a443dff4fcfcfe805b1b11436c54f8e5d264736f6c63430007060033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100415760003560e01c806372f7a95614610046578063d9a208121461007a578063ef2624ae146100de575b600080fd5b61004e610122565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100dc6004803603604081101561009057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610146565b005b610120600480360360208110156100f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b6e565b005b7f000000000000000000000000717d8fbf96440d203dd53644b26f960f6917684a81565b7f000000000000000000000000717d8fbf96440d203dd53644b26f960f6917684a73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614156101eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001806115646030913960400191505060405180910390fd5b600160055414610246576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806116116022913960400191505060405180910390fd5b61024f81611263565b6102a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806115946021913960400191505060405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b815260040160006040518083038186803b15801561030d57600080fd5b505afa158015610321573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561034b57600080fd5b810190808051604051939291908464010000000082111561036b57600080fd5b8382019150602082018581111561038157600080fd5b825186600182028301116401000000008211171561039e57600080fd5b8083526020830192505050908051906020019080838360005b838110156103d25780820151818401526020810190506103b7565b50505050905090810190601f1680156103ff5780820380516001836020036101000a031916815260200191505b506040525050506040516020018082805190602001908083835b6020831061043c5780518252602082019150602081019050602083039250610419565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405160200180807f312e312e310000000000000000000000000000000000000000000000000000008152506005019050604051602081830303815290604052805190602001208114610517576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806115b5602b913960400191505060405180910390fd5b60008373ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b815260040160006040518083038186803b15801561055f57600080fd5b505afa158015610573573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561059d57600080fd5b81019080805160405193929190846401000000008211156105bd57600080fd5b838201915060208201858111156105d357600080fd5b82518660018202830111640100000000821117156105f057600080fd5b8083526020830192505050908051906020019080838360005b83811015610624578082015181840152602081019050610609565b50505050905090810190601f1680156106515780820380516001836020036101000a031916815260200191505b506040525050506040516020018082805190602001908083835b6020831061068e578051825260208201915060208101905060208303925061066b565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405160200180807f312e332e30000000000000000000000000000000000000000000000000000000815250600501905060405160208183030381529060405280519060200120811480610764575060405160200180807f312e342e3100000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040528051906020012081145b6107b9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806115b5602b913960400191505060405180910390fd5b60003090508073ffffffffffffffffffffffffffffffffffffffff1663f08a0323856040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b15801561082757600080fd5b505af115801561083b573d6000803e3d6000fd5b505050507f000000000000000000000000717d8fbf96440d203dd53644b26f960f6917684a73ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88273ffffffffffffffffffffffffffffffffffffffff1663a0e67e2b6040518163ffffffff1660e01b815260040160006040518083038186803b1580156108dd57600080fd5b505afa1580156108f1573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561091b57600080fd5b810190808051604051939291908464010000000082111561093b57600080fd5b8382019150602082018581111561095157600080fd5b825186602082028301116401000000008211171561096e57600080fd5b8083526020830192505050908051906020019060200280838360005b838110156109a557808201518184015260208101905061098a565b505050509050016040525050508373ffffffffffffffffffffffffffffffffffffffff1663e75235b86040518163ffffffff1660e01b815260040160206040518083038186803b1580156109f857600080fd5b505afa158015610a0c573d6000803e3d6000fd5b505050506040513d6020811015610a2257600080fd5b810190808051906020019092919050505060008860405180806020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828103825286818151815260200191508051906020019060200280838360005b83811015610ab7578082015181840152602081019050610a9c565b505050509050019550505050505060405180910390a2600063d9a208128686604051602401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff168152602001925050506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050610b668682611276565b505050505050565b7f000000000000000000000000717d8fbf96440d203dd53644b26f960f6917684a73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161415610c13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001806115646030913960400191505060405180910390fd5b600160055414610c6e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806116116022913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610d13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806115416023913960400191505060405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b815260040160006040518083038186803b158015610d7c57600080fd5b505afa158015610d90573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506020811015610dba57600080fd5b8101908080516040519392919084640100000000821115610dda57600080fd5b83820191506020820185811115610df057600080fd5b8251866001820283011164010000000082111715610e0d57600080fd5b8083526020830192505050908051906020019080838360005b83811015610e41578082015181840152602081019050610e26565b50505050905090810190601f168015610e6e5780820380516001836020036101000a031916815260200191505b506040525050506040516020018082805190602001908083835b60208310610eab5780518252602082019150602081019050602083039250610e88565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060008273ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b815260040160006040518083038186803b158015610f3057600080fd5b505afa158015610f44573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506020811015610f6e57600080fd5b8101908080516040519392919084640100000000821115610f8e57600080fd5b83820191506020820185811115610fa457600080fd5b8251866001820283011164010000000082111715610fc157600080fd5b8083526020830192505050908051906020019080838360005b83811015610ff5578082015181840152602081019050610fda565b50505050905090810190601f1680156110225780820380516001836020036101000a031916815260200191505b506040525050506040516020018082805190602001908083835b6020831061105f578051825260208201915060208101905060208303925061103c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012090508082146110f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001806115e06031913960400191505060405180910390fd5b60405160200180807f312e332e3000000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040528051906020012081148061118d575060405160200180807f312e342e3100000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040528051906020012081145b6111e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806115b5602b913960400191505060405180910390fd5b600063ef2624ae84604051602401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905061125d8482611276565b50505050565b600080823b905060008111915050919050565b816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008033600454604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405160208183030381529060405290507f66753cd2356569ee081232e3be8909b950e0a76c1f8460c3a5e3c2be32b11bed7f000000000000000000000000717d8fbf96440d203dd53644b26f960f6917684a600084600160008060008060008a604051808b73ffffffffffffffffffffffffffffffffffffffff1681526020018a81526020018060200189600181111561138857fe5b81526020018881526020018781526020018681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff168152602001806020018060200184810384528c818151815260200191508051906020019080838360005b838110156114175780820151818401526020810190506113fc565b50505050905090810190601f1680156114445780820380516001836020036101000a031916815260200191505b50848103835260008152602001848103825285818151815260200191508051906020019080838360005b8381101561148957808201518184015260208101905061146e565b50505050905090810190601f1680156114b65780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a17f75e41bc35ff1bf14d81d1d2f649c0084a0f974f9289c803ec9898eeec4c8d0b860008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150505056fe5361666520697320616c7265616479207573696e67207468652073696e676c65746f6e4d6967726174696f6e2073686f756c64206f6e6c792062652063616c6c6564207669612064656c656761746563616c6c66616c6c6261636b48616e646c6572206973206e6f74206120636f6e747261637450726f76696465642073696e676c65746f6e2076657273696f6e206973206e6f7420737570706f727465644c322073696e676c65746f6e206d757374206d617463682063757272656e742076657273696f6e2073696e676c65746f6e53616665206d7573742068617665206e6f7420657865637574656420616e79207478a26469706673582212209e7602ff6f93f41fd0d07e9f6af190a443dff4fcfcfe805b1b11436c54f8e5d264736f6c63430007060033