ETH Price: $3,087.95 (-1.33%)
Gas: 3 Gwei

Contract

0xC3DC853dD716bd5754f421ef94fdCbac3902ab32
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Cancel Migration154585252022-09-02 10:07:46625 days ago1662113266IN
Enzyme Finance: Dispatcher
0 ETH0.0006423711.84328477
Cancel Migration144212212022-03-20 4:58:28791 days ago1647752308IN
Enzyme Finance: Dispatcher
0 ETH0.0010810819.93147324
Cancel Migration143508302022-03-09 5:46:36802 days ago1646804796IN
Enzyme Finance: Dispatcher
0 ETH0.0019343235.66231887
Cancel Migration142705312022-02-24 18:49:29815 days ago1645728569IN
Enzyme Finance: Dispatcher
0 ETH0.0024800545.72364077
Cancel Migration142367462022-02-19 13:26:59820 days ago1645277219IN
Enzyme Finance: Dispatcher
0 ETH0.0026401648.67559303
Cancel Migration141838232022-02-11 9:02:41828 days ago1644570161IN
Enzyme Finance: Dispatcher
0 ETH0.0023269442.90084223
Set Nominated Ow...116399062021-01-12 11:47:191223 days ago1610452039IN
Enzyme Finance: Dispatcher
0 ETH0.0030567266
0x60806040116364932021-01-11 23:00:071224 days ago1610406007IN
 Create: Dispatcher
0 ETH0.2365972797.9

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
198912282024-05-17 17:37:592 days ago1715967479
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
198488302024-05-11 19:18:478 days ago1715455127
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
198415152024-05-10 18:45:599 days ago1715366759
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
198147812024-05-07 1:01:1113 days ago1715043671
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
197860702024-05-03 0:40:1117 days ago1714696811
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
197145752024-04-23 0:40:5927 days ago1713832859
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
196915162024-04-19 19:18:3530 days ago1713554315
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
196822832024-04-18 12:16:2331 days ago1713442583
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
196409172024-04-12 17:08:4737 days ago1712941727
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
196244312024-04-10 9:46:5939 days ago1712742419
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
196176562024-04-09 11:01:3540 days ago1712660495
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
195884212024-04-05 8:42:1144 days ago1712306531
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
195872092024-04-05 4:37:3544 days ago1712291855
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
194960622024-03-23 8:18:2357 days ago1711181903
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
193849532024-03-07 18:01:5973 days ago1709834519
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
193846612024-03-07 17:03:2373 days ago1709831003
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
193721682024-03-05 23:11:3575 days ago1709680295
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
193162082024-02-27 3:29:1183 days ago1709004551
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
193071032024-02-25 20:52:4784 days ago1708894367
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
192922612024-02-23 19:05:2386 days ago1708715123
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
192820682024-02-22 8:47:4787 days ago1708591667
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
192577632024-02-18 22:53:1191 days ago1708296791
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
192422292024-02-16 18:26:5993 days ago1708108019
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
192331372024-02-15 11:49:4794 days ago1707997787
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
191737462024-02-07 3:49:11103 days ago1707277751
Enzyme Finance: Dispatcher
 Contract Creation0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Dispatcher

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license
File 1 of 6 : Dispatcher.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.6.12;

import "../utils/IMigrationHookHandler.sol";
import "../utils/IMigratableVault.sol";
import "../vault/VaultProxy.sol";
import "./IDispatcher.sol";

/// @title Dispatcher Contract
/// @author Enzyme Council <[email protected]>
/// @notice The top-level contract linking multiple releases.
/// It handles the deployment of new VaultProxy instances,
/// and the regulation of fund migration from a previous release to the current one.
/// It can also be referred to for access-control based on this contract's owner.
/// @dev DO NOT EDIT CONTRACT
contract Dispatcher is IDispatcher {
    event CurrentFundDeployerSet(address prevFundDeployer, address nextFundDeployer);

    event MigrationCancelled(
        address indexed vaultProxy,
        address indexed prevFundDeployer,
        address indexed nextFundDeployer,
        address nextVaultAccessor,
        address nextVaultLib,
        uint256 executableTimestamp
    );

    event MigrationExecuted(
        address indexed vaultProxy,
        address indexed prevFundDeployer,
        address indexed nextFundDeployer,
        address nextVaultAccessor,
        address nextVaultLib,
        uint256 executableTimestamp
    );

    event MigrationSignaled(
        address indexed vaultProxy,
        address indexed prevFundDeployer,
        address indexed nextFundDeployer,
        address nextVaultAccessor,
        address nextVaultLib,
        uint256 executableTimestamp
    );

    event MigrationTimelockSet(uint256 prevTimelock, uint256 nextTimelock);

    event NominatedOwnerSet(address indexed nominatedOwner);

    event NominatedOwnerRemoved(address indexed nominatedOwner);

    event OwnershipTransferred(address indexed prevOwner, address indexed nextOwner);

    event MigrationInCancelHookFailed(
        bytes failureReturnData,
        address indexed vaultProxy,
        address indexed prevFundDeployer,
        address indexed nextFundDeployer,
        address nextVaultAccessor,
        address nextVaultLib
    );

    event MigrationOutHookFailed(
        bytes failureReturnData,
        IMigrationHookHandler.MigrationOutHook hook,
        address indexed vaultProxy,
        address indexed prevFundDeployer,
        address indexed nextFundDeployer,
        address nextVaultAccessor,
        address nextVaultLib
    );

    event SharesTokenSymbolSet(string _nextSymbol);

    event VaultProxyDeployed(
        address indexed fundDeployer,
        address indexed owner,
        address vaultProxy,
        address indexed vaultLib,
        address vaultAccessor,
        string fundName
    );

    struct MigrationRequest {
        address nextFundDeployer;
        address nextVaultAccessor;
        address nextVaultLib;
        uint256 executableTimestamp;
    }

    address private currentFundDeployer;
    address private nominatedOwner;
    address private owner;
    uint256 private migrationTimelock;
    string private sharesTokenSymbol;
    mapping(address => address) private vaultProxyToFundDeployer;
    mapping(address => MigrationRequest) private vaultProxyToMigrationRequest;

    modifier onlyCurrentFundDeployer() {
        require(
            msg.sender == currentFundDeployer,
            "Only the current FundDeployer can call this function"
        );
        _;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Only the contract owner can call this function");
        _;
    }

    constructor() public {
        migrationTimelock = 2 days;
        owner = msg.sender;
        sharesTokenSymbol = "ENZF";
    }

    /////////////
    // GENERAL //
    /////////////

    /// @notice Sets a new `symbol` value for VaultProxy instances
    /// @param _nextSymbol The symbol value to set
    function setSharesTokenSymbol(string calldata _nextSymbol) external override onlyOwner {
        sharesTokenSymbol = _nextSymbol;

        emit SharesTokenSymbolSet(_nextSymbol);
    }

    ////////////////////
    // ACCESS CONTROL //
    ////////////////////

    /// @notice Claim ownership of the contract
    function claimOwnership() external override {
        address nextOwner = nominatedOwner;
        require(
            msg.sender == nextOwner,
            "claimOwnership: Only the nominatedOwner can call this function"
        );

        delete nominatedOwner;

        address prevOwner = owner;
        owner = nextOwner;

        emit OwnershipTransferred(prevOwner, nextOwner);
    }

    /// @notice Revoke the nomination of a new contract owner
    function removeNominatedOwner() external override onlyOwner {
        address removedNominatedOwner = nominatedOwner;
        require(
            removedNominatedOwner != address(0),
            "removeNominatedOwner: There is no nominated owner"
        );

        delete nominatedOwner;

        emit NominatedOwnerRemoved(removedNominatedOwner);
    }

    /// @notice Set a new FundDeployer for use within the contract
    /// @param _nextFundDeployer The address of the FundDeployer contract
    function setCurrentFundDeployer(address _nextFundDeployer) external override onlyOwner {
        require(
            _nextFundDeployer != address(0),
            "setCurrentFundDeployer: _nextFundDeployer cannot be empty"
        );
        require(
            __isContract(_nextFundDeployer),
            "setCurrentFundDeployer: Non-contract _nextFundDeployer"
        );

        address prevFundDeployer = currentFundDeployer;
        require(
            _nextFundDeployer != prevFundDeployer,
            "setCurrentFundDeployer: _nextFundDeployer is already currentFundDeployer"
        );

        currentFundDeployer = _nextFundDeployer;

        emit CurrentFundDeployerSet(prevFundDeployer, _nextFundDeployer);
    }

    /// @notice Nominate a new contract owner
    /// @param _nextNominatedOwner The account to nominate
    /// @dev Does not prohibit overwriting the current nominatedOwner
    function setNominatedOwner(address _nextNominatedOwner) external override onlyOwner {
        require(
            _nextNominatedOwner != address(0),
            "setNominatedOwner: _nextNominatedOwner cannot be empty"
        );
        require(
            _nextNominatedOwner != owner,
            "setNominatedOwner: _nextNominatedOwner is already the owner"
        );
        require(
            _nextNominatedOwner != nominatedOwner,
            "setNominatedOwner: _nextNominatedOwner is already nominated"
        );

        nominatedOwner = _nextNominatedOwner;

        emit NominatedOwnerSet(_nextNominatedOwner);
    }

    /// @dev Helper to check whether an address is a deployed contract
    function __isContract(address _who) private view returns (bool isContract_) {
        uint256 size;
        assembly {
            size := extcodesize(_who)
        }

        return size > 0;
    }

    ////////////////
    // DEPLOYMENT //
    ////////////////

    /// @notice Deploys a VaultProxy
    /// @param _vaultLib The VaultLib library with which to instantiate the VaultProxy
    /// @param _owner The account to set as the VaultProxy's owner
    /// @param _vaultAccessor The account to set as the VaultProxy's permissioned accessor
    /// @param _fundName The name of the fund
    /// @dev Input validation should be handled by the VaultProxy during deployment
    function deployVaultProxy(
        address _vaultLib,
        address _owner,
        address _vaultAccessor,
        string calldata _fundName
    ) external override onlyCurrentFundDeployer returns (address vaultProxy_) {
        require(__isContract(_vaultAccessor), "deployVaultProxy: Non-contract _vaultAccessor");

        bytes memory constructData = abi.encodeWithSelector(
            IMigratableVault.init.selector,
            _owner,
            _vaultAccessor,
            _fundName
        );
        vaultProxy_ = address(new VaultProxy(constructData, _vaultLib));

        address fundDeployer = msg.sender;
        vaultProxyToFundDeployer[vaultProxy_] = fundDeployer;

        emit VaultProxyDeployed(
            fundDeployer,
            _owner,
            vaultProxy_,
            _vaultLib,
            _vaultAccessor,
            _fundName
        );

        return vaultProxy_;
    }

    ////////////////
    // MIGRATIONS //
    ////////////////

    /// @notice Cancels a pending migration request
    /// @param _vaultProxy The VaultProxy contract for which to cancel the migration request
    /// @param _bypassFailure True if a failure in either migration hook should be ignored
    /// @dev Because this function must also be callable by a permissioned migrator, it has an
    /// extra migration hook to the nextFundDeployer for the case where cancelMigration()
    /// is called directly (rather than via the nextFundDeployer).
    function cancelMigration(address _vaultProxy, bool _bypassFailure) external override {
        MigrationRequest memory request = vaultProxyToMigrationRequest[_vaultProxy];
        address nextFundDeployer = request.nextFundDeployer;
        require(nextFundDeployer != address(0), "cancelMigration: No migration request exists");

        // TODO: confirm that if canMigrate() does not exist but the caller is a valid FundDeployer, this still works.
        require(
            msg.sender == nextFundDeployer || IMigratableVault(_vaultProxy).canMigrate(msg.sender),
            "cancelMigration: Not an allowed caller"
        );

        address prevFundDeployer = vaultProxyToFundDeployer[_vaultProxy];
        address nextVaultAccessor = request.nextVaultAccessor;
        address nextVaultLib = request.nextVaultLib;
        uint256 executableTimestamp = request.executableTimestamp;

        delete vaultProxyToMigrationRequest[_vaultProxy];

        __invokeMigrationOutHook(
            IMigrationHookHandler.MigrationOutHook.PostCancel,
            _vaultProxy,
            prevFundDeployer,
            nextFundDeployer,
            nextVaultAccessor,
            nextVaultLib,
            _bypassFailure
        );
        __invokeMigrationInCancelHook(
            _vaultProxy,
            prevFundDeployer,
            nextFundDeployer,
            nextVaultAccessor,
            nextVaultLib,
            _bypassFailure
        );

        emit MigrationCancelled(
            _vaultProxy,
            prevFundDeployer,
            nextFundDeployer,
            nextVaultAccessor,
            nextVaultLib,
            executableTimestamp
        );
    }

    /// @notice Executes a pending migration request
    /// @param _vaultProxy The VaultProxy contract for which to execute the migration request
    /// @param _bypassFailure True if a failure in either migration hook should be ignored
    function executeMigration(address _vaultProxy, bool _bypassFailure) external override {
        MigrationRequest memory request = vaultProxyToMigrationRequest[_vaultProxy];
        address nextFundDeployer = request.nextFundDeployer;
        require(
            nextFundDeployer != address(0),
            "executeMigration: No migration request exists for _vaultProxy"
        );
        require(
            msg.sender == nextFundDeployer,
            "executeMigration: Only the target FundDeployer can call this function"
        );
        require(
            nextFundDeployer == currentFundDeployer,
            "executeMigration: The target FundDeployer is no longer the current FundDeployer"
        );
        uint256 executableTimestamp = request.executableTimestamp;
        require(
            block.timestamp >= executableTimestamp,
            "executeMigration: The migration timelock has not elapsed"
        );

        address prevFundDeployer = vaultProxyToFundDeployer[_vaultProxy];
        address nextVaultAccessor = request.nextVaultAccessor;
        address nextVaultLib = request.nextVaultLib;

        __invokeMigrationOutHook(
            IMigrationHookHandler.MigrationOutHook.PreMigrate,
            _vaultProxy,
            prevFundDeployer,
            nextFundDeployer,
            nextVaultAccessor,
            nextVaultLib,
            _bypassFailure
        );

        // Upgrade the VaultProxy to a new VaultLib and update the accessor via the new VaultLib
        IMigratableVault(_vaultProxy).setVaultLib(nextVaultLib);
        IMigratableVault(_vaultProxy).setAccessor(nextVaultAccessor);

        // Update the FundDeployer that migrated the VaultProxy
        vaultProxyToFundDeployer[_vaultProxy] = nextFundDeployer;

        // Remove the migration request
        delete vaultProxyToMigrationRequest[_vaultProxy];

        __invokeMigrationOutHook(
            IMigrationHookHandler.MigrationOutHook.PostMigrate,
            _vaultProxy,
            prevFundDeployer,
            nextFundDeployer,
            nextVaultAccessor,
            nextVaultLib,
            _bypassFailure
        );

        emit MigrationExecuted(
            _vaultProxy,
            prevFundDeployer,
            nextFundDeployer,
            nextVaultAccessor,
            nextVaultLib,
            executableTimestamp
        );
    }

    /// @notice Sets a new migration timelock
    /// @param _nextTimelock The number of seconds for the new timelock
    function setMigrationTimelock(uint256 _nextTimelock) external override onlyOwner {
        uint256 prevTimelock = migrationTimelock;
        require(
            _nextTimelock != prevTimelock,
            "setMigrationTimelock: _nextTimelock is the current timelock"
        );

        migrationTimelock = _nextTimelock;

        emit MigrationTimelockSet(prevTimelock, _nextTimelock);
    }

    /// @notice Signals a migration by creating a migration request
    /// @param _vaultProxy The VaultProxy contract for which to signal migration
    /// @param _nextVaultAccessor The account that will be the next `accessor` on the VaultProxy
    /// @param _nextVaultLib The next VaultLib library contract address to set on the VaultProxy
    /// @param _bypassFailure True if a failure in either migration hook should be ignored
    function signalMigration(
        address _vaultProxy,
        address _nextVaultAccessor,
        address _nextVaultLib,
        bool _bypassFailure
    ) external override onlyCurrentFundDeployer {
        require(
            __isContract(_nextVaultAccessor),
            "signalMigration: Non-contract _nextVaultAccessor"
        );

        address prevFundDeployer = vaultProxyToFundDeployer[_vaultProxy];
        require(prevFundDeployer != address(0), "signalMigration: _vaultProxy does not exist");

        address nextFundDeployer = msg.sender;
        require(
            nextFundDeployer != prevFundDeployer,
            "signalMigration: Can only migrate to a new FundDeployer"
        );

        __invokeMigrationOutHook(
            IMigrationHookHandler.MigrationOutHook.PreSignal,
            _vaultProxy,
            prevFundDeployer,
            nextFundDeployer,
            _nextVaultAccessor,
            _nextVaultLib,
            _bypassFailure
        );

        uint256 executableTimestamp = block.timestamp + migrationTimelock;
        vaultProxyToMigrationRequest[_vaultProxy] = MigrationRequest({
            nextFundDeployer: nextFundDeployer,
            nextVaultAccessor: _nextVaultAccessor,
            nextVaultLib: _nextVaultLib,
            executableTimestamp: executableTimestamp
        });

        __invokeMigrationOutHook(
            IMigrationHookHandler.MigrationOutHook.PostSignal,
            _vaultProxy,
            prevFundDeployer,
            nextFundDeployer,
            _nextVaultAccessor,
            _nextVaultLib,
            _bypassFailure
        );

        emit MigrationSignaled(
            _vaultProxy,
            prevFundDeployer,
            nextFundDeployer,
            _nextVaultAccessor,
            _nextVaultLib,
            executableTimestamp
        );
    }

    /// @dev Helper to invoke a MigrationInCancelHook on the next FundDeployer being "migrated in" to,
    /// which can optionally be implemented on the FundDeployer
    function __invokeMigrationInCancelHook(
        address _vaultProxy,
        address _prevFundDeployer,
        address _nextFundDeployer,
        address _nextVaultAccessor,
        address _nextVaultLib,
        bool _bypassFailure
    ) private {
        (bool success, bytes memory returnData) = _nextFundDeployer.call(
            abi.encodeWithSelector(
                IMigrationHookHandler.invokeMigrationInCancelHook.selector,
                _vaultProxy,
                _prevFundDeployer,
                _nextVaultAccessor,
                _nextVaultLib
            )
        );
        if (!success) {
            require(
                _bypassFailure,
                string(abi.encodePacked("MigrationOutCancelHook: ", returnData))
            );

            emit MigrationInCancelHookFailed(
                returnData,
                _vaultProxy,
                _prevFundDeployer,
                _nextFundDeployer,
                _nextVaultAccessor,
                _nextVaultLib
            );
        }
    }

    /// @dev Helper to invoke a IMigrationHookHandler.MigrationOutHook on the previous FundDeployer being "migrated out" of,
    /// which can optionally be implemented on the FundDeployer
    function __invokeMigrationOutHook(
        IMigrationHookHandler.MigrationOutHook _hook,
        address _vaultProxy,
        address _prevFundDeployer,
        address _nextFundDeployer,
        address _nextVaultAccessor,
        address _nextVaultLib,
        bool _bypassFailure
    ) private {
        (bool success, bytes memory returnData) = _prevFundDeployer.call(
            abi.encodeWithSelector(
                IMigrationHookHandler.invokeMigrationOutHook.selector,
                _hook,
                _vaultProxy,
                _nextFundDeployer,
                _nextVaultAccessor,
                _nextVaultLib
            )
        );
        if (!success) {
            require(
                _bypassFailure,
                string(abi.encodePacked(__migrationOutHookFailureReasonPrefix(_hook), returnData))
            );

            emit MigrationOutHookFailed(
                returnData,
                _hook,
                _vaultProxy,
                _prevFundDeployer,
                _nextFundDeployer,
                _nextVaultAccessor,
                _nextVaultLib
            );
        }
    }

    /// @dev Helper to return a revert reason string prefix for a given MigrationOutHook
    function __migrationOutHookFailureReasonPrefix(IMigrationHookHandler.MigrationOutHook _hook)
        private
        pure
        returns (string memory failureReasonPrefix_)
    {
        if (_hook == IMigrationHookHandler.MigrationOutHook.PreSignal) {
            return "MigrationOutHook.PreSignal: ";
        }
        if (_hook == IMigrationHookHandler.MigrationOutHook.PostSignal) {
            return "MigrationOutHook.PostSignal: ";
        }
        if (_hook == IMigrationHookHandler.MigrationOutHook.PreMigrate) {
            return "MigrationOutHook.PreMigrate: ";
        }
        if (_hook == IMigrationHookHandler.MigrationOutHook.PostMigrate) {
            return "MigrationOutHook.PostMigrate: ";
        }
        if (_hook == IMigrationHookHandler.MigrationOutHook.PostCancel) {
            return "MigrationOutHook.PostCancel: ";
        }

        return "";
    }

    ///////////////////
    // STATE GETTERS //
    ///////////////////

    // Provides several potentially helpful getters that are not strictly necessary

    /// @notice Gets the current FundDeployer that is allowed to deploy and migrate funds
    /// @return currentFundDeployer_ The current FundDeployer contract address
    function getCurrentFundDeployer()
        external
        view
        override
        returns (address currentFundDeployer_)
    {
        return currentFundDeployer;
    }

    /// @notice Gets the FundDeployer with which a given VaultProxy is associated
    /// @param _vaultProxy The VaultProxy instance
    /// @return fundDeployer_ The FundDeployer contract address
    function getFundDeployerForVaultProxy(address _vaultProxy)
        external
        view
        override
        returns (address fundDeployer_)
    {
        return vaultProxyToFundDeployer[_vaultProxy];
    }

    /// @notice Gets the details of a pending migration request for a given VaultProxy
    /// @param _vaultProxy The VaultProxy instance
    /// @return nextFundDeployer_ The FundDeployer contract address from which the migration
    /// request was made
    /// @return nextVaultAccessor_ The account that will be the next `accessor` on the VaultProxy
    /// @return nextVaultLib_ The next VaultLib library contract address to set on the VaultProxy
    /// @return executableTimestamp_ The timestamp at which the migration request can be executed
    function getMigrationRequestDetailsForVaultProxy(address _vaultProxy)
        external
        view
        override
        returns (
            address nextFundDeployer_,
            address nextVaultAccessor_,
            address nextVaultLib_,
            uint256 executableTimestamp_
        )
    {
        MigrationRequest memory r = vaultProxyToMigrationRequest[_vaultProxy];
        if (r.executableTimestamp > 0) {
            return (
                r.nextFundDeployer,
                r.nextVaultAccessor,
                r.nextVaultLib,
                r.executableTimestamp
            );
        }
    }

    /// @notice Gets the amount of time that must pass between signaling and executing a migration
    /// @return migrationTimelock_ The timelock value (in seconds)
    function getMigrationTimelock() external view override returns (uint256 migrationTimelock_) {
        return migrationTimelock;
    }

    /// @notice Gets the account that is nominated to be the next owner of this contract
    /// @return nominatedOwner_ The account that is nominated to be the owner
    function getNominatedOwner() external view override returns (address nominatedOwner_) {
        return nominatedOwner;
    }

    /// @notice Gets the owner of this contract
    /// @return owner_ The account that is the owner
    function getOwner() external view override returns (address owner_) {
        return owner;
    }

    /// @notice Gets the shares token `symbol` value for use in VaultProxy instances
    /// @return sharesTokenSymbol_ The `symbol` value
    function getSharesTokenSymbol()
        external
        view
        override
        returns (string memory sharesTokenSymbol_)
    {
        return sharesTokenSymbol;
    }

    /// @notice Gets the time remaining until the migration request of a given VaultProxy can be executed
    /// @param _vaultProxy The VaultProxy instance
    /// @return secondsRemaining_ The number of seconds remaining on the timelock
    function getTimelockRemainingForMigrationRequest(address _vaultProxy)
        external
        view
        override
        returns (uint256 secondsRemaining_)
    {
        uint256 executableTimestamp = vaultProxyToMigrationRequest[_vaultProxy]
            .executableTimestamp;
        if (executableTimestamp == 0) {
            return 0;
        }

        if (block.timestamp >= executableTimestamp) {
            return 0;
        }

        return executableTimestamp - block.timestamp;
    }

    /// @notice Checks whether a migration request that is executable exists for a given VaultProxy
    /// @param _vaultProxy The VaultProxy instance
    /// @return hasExecutableRequest_ True if a migration request exists and is executable
    function hasExecutableMigrationRequest(address _vaultProxy)
        external
        view
        override
        returns (bool hasExecutableRequest_)
    {
        uint256 executableTimestamp = vaultProxyToMigrationRequest[_vaultProxy]
            .executableTimestamp;

        return executableTimestamp > 0 && block.timestamp >= executableTimestamp;
    }

    /// @notice Checks whether a migration request exists for a given VaultProxy
    /// @param _vaultProxy The VaultProxy instance
    /// @return hasMigrationRequest_ True if a migration request exists
    function hasMigrationRequest(address _vaultProxy)
        external
        view
        override
        returns (bool hasMigrationRequest_)
    {
        return vaultProxyToMigrationRequest[_vaultProxy].executableTimestamp > 0;
    }
}

File 3 of 6 : IDispatcher.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.6.12;

/// @title IDispatcher Interface
/// @author Enzyme Council <[email protected]>
interface IDispatcher {
    function cancelMigration(address _vaultProxy, bool _bypassFailure) external;

    function claimOwnership() external;

    function deployVaultProxy(
        address _vaultLib,
        address _owner,
        address _vaultAccessor,
        string calldata _fundName
    ) external returns (address vaultProxy_);

    function executeMigration(address _vaultProxy, bool _bypassFailure) external;

    function getCurrentFundDeployer() external view returns (address currentFundDeployer_);

    function getFundDeployerForVaultProxy(address _vaultProxy)
        external
        view
        returns (address fundDeployer_);

    function getMigrationRequestDetailsForVaultProxy(address _vaultProxy)
        external
        view
        returns (
            address nextFundDeployer_,
            address nextVaultAccessor_,
            address nextVaultLib_,
            uint256 executableTimestamp_
        );

    function getMigrationTimelock() external view returns (uint256 migrationTimelock_);

    function getNominatedOwner() external view returns (address nominatedOwner_);

    function getOwner() external view returns (address owner_);

    function getSharesTokenSymbol() external view returns (string memory sharesTokenSymbol_);

    function getTimelockRemainingForMigrationRequest(address _vaultProxy)
        external
        view
        returns (uint256 secondsRemaining_);

    function hasExecutableMigrationRequest(address _vaultProxy)
        external
        view
        returns (bool hasExecutableRequest_);

    function hasMigrationRequest(address _vaultProxy)
        external
        view
        returns (bool hasMigrationRequest_);

    function removeNominatedOwner() external;

    function setCurrentFundDeployer(address _nextFundDeployer) external;

    function setMigrationTimelock(uint256 _nextTimelock) external;

    function setNominatedOwner(address _nextNominatedOwner) external;

    function setSharesTokenSymbol(string calldata _nextSymbol) external;

    function signalMigration(
        address _vaultProxy,
        address _nextVaultAccessor,
        address _nextVaultLib,
        bool _bypassFailure
    ) external;
}

File 4 of 6 : IMigratableVault.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.6.12;

/// @title IMigratableVault Interface
/// @author Enzyme Council <[email protected]>
/// @dev DO NOT EDIT CONTRACT
interface IMigratableVault {
    function canMigrate(address _who) external view returns (bool canMigrate_);

    function init(
        address _owner,
        address _accessor,
        string calldata _fundName
    ) external;

    function setAccessor(address _nextAccessor) external;

    function setVaultLib(address _nextVaultLib) external;
}

File 5 of 6 : IMigrationHookHandler.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.6.12;

/// @title IMigrationHookHandler Interface
/// @author Enzyme Council <[email protected]>
interface IMigrationHookHandler {
    enum MigrationOutHook {PreSignal, PostSignal, PreMigrate, PostMigrate, PostCancel}

    function invokeMigrationInCancelHook(
        address _vaultProxy,
        address _prevFundDeployer,
        address _nextVaultAccessor,
        address _nextVaultLib
    ) external;

    function invokeMigrationOutHook(
        MigrationOutHook _hook,
        address _vaultProxy,
        address _nextFundDeployer,
        address _nextVaultAccessor,
        address _nextVaultLib
    ) external;
}

File 6 of 6 : VaultProxy.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.6.12;

import "./utils/ProxiableVaultLib.sol";

/// @title VaultProxy Contract
/// @author Enzyme Council <[email protected]>
/// @notice A proxy contract for all VaultProxy instances, slightly modified from EIP-1822
/// @dev Adapted from the recommended implementation of a Proxy in EIP-1822, updated for solc 0.6.12,
/// and using the EIP-1967 storage slot for the proxiable implementation.
/// i.e., `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)`, which is
/// "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"
/// See: https://eips.ethereum.org/EIPS/eip-1822
contract VaultProxy {
    constructor(bytes memory _constructData, address _vaultLib) public {
        // "0x027b9570e9fedc1a80b937ae9a06861e5faef3992491af30b684a64b3fbec7a5" corresponds to
        // `bytes32(keccak256('mln.proxiable.vaultlib'))`
        require(
            bytes32(0x027b9570e9fedc1a80b937ae9a06861e5faef3992491af30b684a64b3fbec7a5) ==
                ProxiableVaultLib(_vaultLib).proxiableUUID(),
            "constructor: _vaultLib not compatible"
        );

        assembly {
            // solium-disable-line
            sstore(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, _vaultLib)
        }

        (bool success, bytes memory returnData) = _vaultLib.delegatecall(_constructData); // solium-disable-line
        require(success, string(returnData));
    }

    fallback() external payable {
        assembly {
            // solium-disable-line
            let contractLogic := sload(
                0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
            )
            calldatacopy(0x0, 0x0, calldatasize())
            let success := delegatecall(
                sub(gas(), 10000),
                contractLogic,
                0x0,
                calldatasize(),
                0,
                0
            )
            let retSz := returndatasize()
            returndatacopy(0, 0, retSz)
            switch success
                case 0 {
                    revert(0, retSz)
                }
                default {
                    return(0, retSz)
                }
        }
    }
}

File 7 of 6 : ProxiableVaultLib.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.6.12;

/// @title ProxiableVaultLib Contract
/// @author Enzyme Council <[email protected]>
/// @notice A contract that defines the upgrade behavior for VaultLib instances
/// @dev The recommended implementation of the target of a proxy according to EIP-1822 and EIP-1967
/// Code position in storage is `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)`,
/// which is "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc".
abstract contract ProxiableVaultLib {
    /// @dev Updates the target of the proxy to be the contract at _nextVaultLib
    function __updateCodeAddress(address _nextVaultLib) internal {
        require(
            bytes32(0x027b9570e9fedc1a80b937ae9a06861e5faef3992491af30b684a64b3fbec7a5) ==
                ProxiableVaultLib(_nextVaultLib).proxiableUUID(),
            "__updateCodeAddress: _nextVaultLib not compatible"
        );
        assembly {
            // solium-disable-line
            sstore(
                0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,
                _nextVaultLib
            )
        }
    }

    /// @notice Returns a unique bytes32 hash for VaultLib instances
    /// @return uuid_ The bytes32 hash representing the UUID
    /// @dev The UUID is `bytes32(keccak256('mln.proxiable.vaultlib'))`
    function proxiableUUID() public pure returns (bytes32 uuid_) {
        return 0x027b9570e9fedc1a80b937ae9a06861e5faef3992491af30b684a64b3fbec7a5;
    }
}

Settings
{
  "evmVersion": "istanbul",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "details": {
      "constantOptimizer": true,
      "cse": true,
      "deduplicate": true,
      "jumpdestRemover": true,
      "orderLiterals": true,
      "peephole": true,
      "yul": false
    },
    "runs": 200
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"prevFundDeployer","type":"address"},{"indexed":false,"internalType":"address","name":"nextFundDeployer","type":"address"}],"name":"CurrentFundDeployerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vaultProxy","type":"address"},{"indexed":true,"internalType":"address","name":"prevFundDeployer","type":"address"},{"indexed":true,"internalType":"address","name":"nextFundDeployer","type":"address"},{"indexed":false,"internalType":"address","name":"nextVaultAccessor","type":"address"},{"indexed":false,"internalType":"address","name":"nextVaultLib","type":"address"},{"indexed":false,"internalType":"uint256","name":"executableTimestamp","type":"uint256"}],"name":"MigrationCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vaultProxy","type":"address"},{"indexed":true,"internalType":"address","name":"prevFundDeployer","type":"address"},{"indexed":true,"internalType":"address","name":"nextFundDeployer","type":"address"},{"indexed":false,"internalType":"address","name":"nextVaultAccessor","type":"address"},{"indexed":false,"internalType":"address","name":"nextVaultLib","type":"address"},{"indexed":false,"internalType":"uint256","name":"executableTimestamp","type":"uint256"}],"name":"MigrationExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"failureReturnData","type":"bytes"},{"indexed":true,"internalType":"address","name":"vaultProxy","type":"address"},{"indexed":true,"internalType":"address","name":"prevFundDeployer","type":"address"},{"indexed":true,"internalType":"address","name":"nextFundDeployer","type":"address"},{"indexed":false,"internalType":"address","name":"nextVaultAccessor","type":"address"},{"indexed":false,"internalType":"address","name":"nextVaultLib","type":"address"}],"name":"MigrationInCancelHookFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"failureReturnData","type":"bytes"},{"indexed":false,"internalType":"enum IMigrationHookHandler.MigrationOutHook","name":"hook","type":"uint8"},{"indexed":true,"internalType":"address","name":"vaultProxy","type":"address"},{"indexed":true,"internalType":"address","name":"prevFundDeployer","type":"address"},{"indexed":true,"internalType":"address","name":"nextFundDeployer","type":"address"},{"indexed":false,"internalType":"address","name":"nextVaultAccessor","type":"address"},{"indexed":false,"internalType":"address","name":"nextVaultLib","type":"address"}],"name":"MigrationOutHookFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vaultProxy","type":"address"},{"indexed":true,"internalType":"address","name":"prevFundDeployer","type":"address"},{"indexed":true,"internalType":"address","name":"nextFundDeployer","type":"address"},{"indexed":false,"internalType":"address","name":"nextVaultAccessor","type":"address"},{"indexed":false,"internalType":"address","name":"nextVaultLib","type":"address"},{"indexed":false,"internalType":"uint256","name":"executableTimestamp","type":"uint256"}],"name":"MigrationSignaled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevTimelock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nextTimelock","type":"uint256"}],"name":"MigrationTimelockSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nominatedOwner","type":"address"}],"name":"NominatedOwnerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nominatedOwner","type":"address"}],"name":"NominatedOwnerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevOwner","type":"address"},{"indexed":true,"internalType":"address","name":"nextOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_nextSymbol","type":"string"}],"name":"SharesTokenSymbolSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fundDeployer","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"vaultProxy","type":"address"},{"indexed":true,"internalType":"address","name":"vaultLib","type":"address"},{"indexed":false,"internalType":"address","name":"vaultAccessor","type":"address"},{"indexed":false,"internalType":"string","name":"fundName","type":"string"}],"name":"VaultProxyDeployed","type":"event"},{"inputs":[{"internalType":"address","name":"_vaultProxy","type":"address"},{"internalType":"bool","name":"_bypassFailure","type":"bool"}],"name":"cancelMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultLib","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_vaultAccessor","type":"address"},{"internalType":"string","name":"_fundName","type":"string"}],"name":"deployVaultProxy","outputs":[{"internalType":"address","name":"vaultProxy_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultProxy","type":"address"},{"internalType":"bool","name":"_bypassFailure","type":"bool"}],"name":"executeMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCurrentFundDeployer","outputs":[{"internalType":"address","name":"currentFundDeployer_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultProxy","type":"address"}],"name":"getFundDeployerForVaultProxy","outputs":[{"internalType":"address","name":"fundDeployer_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultProxy","type":"address"}],"name":"getMigrationRequestDetailsForVaultProxy","outputs":[{"internalType":"address","name":"nextFundDeployer_","type":"address"},{"internalType":"address","name":"nextVaultAccessor_","type":"address"},{"internalType":"address","name":"nextVaultLib_","type":"address"},{"internalType":"uint256","name":"executableTimestamp_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMigrationTimelock","outputs":[{"internalType":"uint256","name":"migrationTimelock_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNominatedOwner","outputs":[{"internalType":"address","name":"nominatedOwner_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSharesTokenSymbol","outputs":[{"internalType":"string","name":"sharesTokenSymbol_","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultProxy","type":"address"}],"name":"getTimelockRemainingForMigrationRequest","outputs":[{"internalType":"uint256","name":"secondsRemaining_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultProxy","type":"address"}],"name":"hasExecutableMigrationRequest","outputs":[{"internalType":"bool","name":"hasExecutableRequest_","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultProxy","type":"address"}],"name":"hasMigrationRequest","outputs":[{"internalType":"bool","name":"hasMigrationRequest_","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"removeNominatedOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nextFundDeployer","type":"address"}],"name":"setCurrentFundDeployer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextTimelock","type":"uint256"}],"name":"setMigrationTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nextNominatedOwner","type":"address"}],"name":"setNominatedOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_nextSymbol","type":"string"}],"name":"setSharesTokenSymbol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultProxy","type":"address"},{"internalType":"address","name":"_nextVaultAccessor","type":"address"},{"internalType":"address","name":"_nextVaultLib","type":"address"},{"internalType":"bool","name":"_bypassFailure","type":"bool"}],"name":"signalMigration","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506202a300600355600280546001600160a01b031916331790556040805180820190915260048082526322a72d2360e11b60209092019182526200005691816200005d565b50620000f9565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000a057805160ff1916838001178555620000d0565b82800160010185558215620000d0579182015b82811115620000d0578251825591602001919060010190620000b3565b50620000de929150620000e2565b5090565b5b80821115620000de5760008155600101620000e3565b61299d80620001096000396000f3fe60806040523480156200001157600080fd5b5060043610620001485760003560e01c806377a8c62411620000bd57806397af7050116200007b57806397af7050146200042d5780639c9d48da1462000456578063b47b06001462000487578063d0449d3d1462000509578063d15f9b9c14620005325762000148565b806377a8c62414620003885780637c77b2ed14620003b15780637dad9fc814620003bb5780638156eecf1462000419578063893d20e814620004235762000148565b80633d7c74f8116200010b5780633d7c74f814620002795780634e71e0c814620002a257806366231cea14620002ac578063728e17a014620002e9578063757bc0dd14620003125762000148565b80631df419f7146200014d57806322a0c08b146200016f578063288b6a3614620002225780632fa0c161146200022c57806338b3eb1b1462000248575b600080fd5b6200016d600480360360208110156200016557600080fd5b503562000573565b005b62000206600480360360808110156200018757600080fd5b6001600160a01b0382358116926020810135821692604082013590921691810190608081016060820135640100000000811115620001c457600080fd5b820183602082011115620001d757600080fd5b80359060200191846001830284011164010000000083111715620001fa57600080fd5b50909250905062000646565b604080516001600160a01b039092168252519081900360200190f35b62000206620008df565b62000236620008ee565b60408051918252519081900360200190f35b6200016d600480360360408110156200026057600080fd5b506001600160a01b0381351690602001351515620008f4565b62000206600480360360208110156200029157600080fd5b50356001600160a01b031662000c46565b6200016d62000c67565b620002d560048036036020811015620002c457600080fd5b50356001600160a01b031662000d10565b604080519115158252519081900360200190f35b6200016d600480360360208110156200030157600080fd5b50356001600160a01b031662000d43565b6200016d600480360360208110156200032a57600080fd5b8101906020810181356401000000008111156200034657600080fd5b8201836020820111156200035957600080fd5b803590602001918460018302840111640100000000831117156200037c57600080fd5b50909250905062000ebd565b6200023660048036036020811015620003a057600080fd5b50356001600160a01b031662000f7b565b6200020662000fc4565b620003e460048036036020811015620003d357600080fd5b50356001600160a01b031662000fd3565b604080516001600160a01b03958616815293851660208501529190931682820152606082019290925290519081900360800190f35b6200016d6200106b565b6200020662001147565b6200016d600480360360208110156200044557600080fd5b50356001600160a01b031662001156565b6200016d600480360360408110156200046e57600080fd5b506001600160a01b0381351690602001351515620012e1565b620004916200152a565b6040805160208082528351818301528351919283929083019185019080838360005b83811015620004cd578181015183820152602001620004b3565b50505050905090810190601f168015620004fb5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b620002d5600480360360208110156200052157600080fd5b50356001600160a01b0316620015c4565b6200016d600480360360808110156200054a57600080fd5b506001600160a01b038135811691602081013582169160408201351690606001351515620015e4565b6002546001600160a01b03163314620005be5760405162461bcd60e51b815260040180806020018281038252602e81526020018062002665602e913960400191505060405180910390fd5b60035481811415620006025760405162461bcd60e51b815260040180806020018281038252603b8152602001806200292d603b913960400191505060405180910390fd5b6003829055604080518281526020810184905281517f481ce28a1145a5d9b59e2d1d7eba33bc3350124def8fdc91032238d343ad5361929181900390910190a15050565b600080546001600160a01b03163314620006925760405162461bcd60e51b8152600401808060200182810382526034815260200180620024df6034913960400191505060405180910390fd5b6200069d8462001832565b620006da5760405162461bcd60e51b815260040180806020018281038252602d815260200180620026c4602d913960400191505060405180910390fd5b6060635c9a6d3760e01b8686868660405160240180856001600160a01b03168152602001846001600160a01b0316815260200180602001828103825284848281815260200192508082843760008382015260408051601f909201601f1990811690940182810390940182529283526020810180516001600160e01b03166001600160e01b0319909b169a909a17909952505196975087968e965062000786955093506200204c92505050565b8080602001836001600160a01b03168152602001828103825284818151815260200191508051906020019080838360005b83811015620007d1578181015183820152602001620007b7565b50505050905090810190601f168015620007ff5780820380516001836020036101000a031916815260200191505b509350505050604051809103906000f08015801562000822573d6000803e3d6000fd5b506001600160a01b0380821660008181526005602090815260409182902080546001600160a01b0319163390811790915582519384528a85169184019190915260609183018281529183018890529395508a8316928a169184917fa50560b448ad796ef60adfeffe1c19ed34daf94c2aa6905d0e209017dbc19f589188918c918c918c919060808201848480828437600083820152604051601f909101601f191690920182900397509095505050505050a4505095945050505050565b6001546001600160a01b031690565b60035490565b620008fe6200205a565b506001600160a01b038083166000908152600660209081526040918290208251608081018452815485168082526001830154861693820193909352600282015490941692840192909252600390910154606083015280620009915760405162461bcd60e51b815260040180806020018281038252603d815260200180620028f0603d913960400191505060405180910390fd5b336001600160a01b03821614620009da5760405162461bcd60e51b8152600401808060200182810382526045815260200180620027c56045913960600191505060405180910390fd5b6000546001600160a01b0382811691161462000a285760405162461bcd60e51b815260040180806020018281038252604f81526020018062002616604f913960600191505060405180910390fd5b60608201514281111562000a6e5760405162461bcd60e51b8152600401808060200182810382526038815260200180620027526038913960400191505060405180910390fd5b6001600160a01b0380861660009081526005602090815260409182902054908601519186015192169162000aa9600289858886868d62001838565b876001600160a01b0316634140d607826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b15801562000af957600080fd5b505af115801562000b0e573d6000803e3d6000fd5b50505050876001600160a01b031663ab9253ac836040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b15801562000b6257600080fd5b505af115801562000b77573d6000803e3d6000fd5b5050506001600160a01b03808a1660009081526005602090815260408083208054948b166001600160a01b0319958616179055600690915281208054831681556001810180548416905560028101805490931690925560039182015562000be5915089858886868d62001838565b604080516001600160a01b038481168252838116602083015281830187905291518288169286811692908c16917fad6fb3d36e2cda148dfd43203c1a40c0da9a9baa662ae9d6c3b0c3e4a9d6a6359181900360600190a45050505050505050565b6001600160a01b03808216600090815260056020526040902054165b919050565b6001546001600160a01b031633811462000cb35760405162461bcd60e51b815260040180806020018281038252603e81526020018062002845603e913960400191505060405180910390fd5b600180546001600160a01b0319908116909155600280546001600160a01b0384811693821684179092556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038116600090815260066020526040812060030154801580159062000d3c5750804210155b9392505050565b6002546001600160a01b0316331462000d8e5760405162461bcd60e51b815260040180806020018281038252602e81526020018062002665602e913960400191505060405180910390fd5b6001600160a01b03811662000dd55760405162461bcd60e51b8152600401808060200182810382526036815260200180620026f16036913960400191505060405180910390fd5b6002546001600160a01b038281169116141562000e245760405162461bcd60e51b815260040180806020018281038252603b8152602001806200278a603b913960400191505060405180910390fd5b6001546001600160a01b038281169116141562000e735760405162461bcd60e51b815260040180806020018281038252603b8152602001806200280a603b913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f132c19de901bb4ed8403c34734b6c841d5dc57745824da452a52433519ea5abf90600090a250565b6002546001600160a01b0316331462000f085760405162461bcd60e51b815260040180806020018281038252602e81526020018062002665602e913960400191505060405180910390fd5b62000f166004838362002081565b507ff0115712c23b609855a28d7b8963c6d16d732ae388b11e5d4ec6d5eae4ad8698828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6001600160a01b0381166000908152600660205260408120600301548062000fa857600091505062000c62565b80421062000fbb57600091505062000c62565b42900392915050565b6000546001600160a01b031690565b60008060008062000fe36200205a565b506001600160a01b038086166000908152600660209081526040918290208251608081018452815485168152600182015485169281019290925260028101549093169181019190915260039091015460608201819052156200106257806000015181602001518260400151836060015194509450945094505062001064565b505b9193509193565b6002546001600160a01b03163314620010b65760405162461bcd60e51b815260040180806020018281038252602e81526020018062002665602e913960400191505060405180910390fd5b6001546001600160a01b031680620011005760405162461bcd60e51b8152600401808060200182810382526031815260200180620026936031913960400191505060405180910390fd5b600180546001600160a01b03191690556040516001600160a01b038216907fe4136584a5e8bb85d66301f3ce8b11cc2e5a8bea3979f10ea2451353849acc4790600090a250565b6002546001600160a01b031690565b6002546001600160a01b03163314620011a15760405162461bcd60e51b815260040180806020018281038252602e81526020018062002665602e913960400191505060405180910390fd5b6001600160a01b038116620011e85760405162461bcd60e51b8152600401808060200182810382526039815260200180620025b76039913960400191505060405180910390fd5b620011f38162001832565b620012305760405162461bcd60e51b8152600401808060200182810382526036815260200180620028ba6036913960400191505060405180910390fd5b6000546001600160a01b03908116908216811415620012815760405162461bcd60e51b8152600401808060200182810382526048815260200180620025436048913960600191505060405180910390fd5b600080546001600160a01b0319166001600160a01b03848116918217909255604080519284168352602083019190915280517f44cf34a26ccbaa8a20e6098a1278e28682572ec9921eb43d8dab274a503e92f59281900390910190a15050565b620012eb6200205a565b506001600160a01b0380831660009081526006602090815260409182902082516080810184528154851680825260018301548616938201939093526002820154909416928401929092526003909101546060830152806200137e5760405162461bcd60e51b815260040180806020018281038252602c8152602001806200258b602c913960400191505060405180910390fd5b336001600160a01b038216148062001407575060408051633ef03e7560e11b815233600482015290516001600160a01b03861691637de07cea916024808301926020929190829003018186803b158015620013d857600080fd5b505afa158015620013ed573d6000803e3d6000fd5b505050506040513d60208110156200140457600080fd5b50515b620014445760405162461bcd60e51b8152600401808060200182810382526026815260200180620025f06026913960400191505060405180910390fd5b6001600160a01b0380851660009081526005602090815260408083205486830151878301516060890151600690955292852080546001600160a01b03199081168255600182018054821690556002820180549091169055600301949094559093169290620014b9600489868887878d62001838565b620014c988858786868c62001bd1565b604080516001600160a01b038581168252848116602083015281830184905291518288169287811692908c16917f9851a8f232c380eb2c1065756776e37d85d4fe0c8cb4005b0d72c749bfef923e9181900360600190a45050505050505050565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620015ba5780601f106200158e57610100808354040283529160200191620015ba565b820191906000526020600020905b8154815290600101906020018083116200159c57829003601f168201915b5050505050905090565b6001600160a01b0316600090815260066020526040902060030154151590565b6000546001600160a01b031633146200162f5760405162461bcd60e51b8152600401808060200182810382526034815260200180620024df6034913960400191505060405180910390fd5b6200163a8362001832565b620016775760405162461bcd60e51b8152600401808060200182810382526030815260200180620025136030913960400191505060405180910390fd5b6001600160a01b038085166000908152600560205260409020541680620016d05760405162461bcd60e51b815260040180806020018281038252602b81526020018062002727602b913960400191505060405180910390fd5b336001600160a01b0382168114156200171b5760405162461bcd60e51b8152600401808060200182810382526037815260200180620028836037913960400191505060405180910390fd5b6200172d600087848489898962001838565b60038054604080516080810182526001600160a01b03808616825289811660208084019182528a831684860190815242909601606085018181528e85166000908152600690935295909120935184549084166001600160a01b0319918216178555915160018086018054928616928516929092179091559551600285018054919094169216919091179091559151930192909255620017d2908885858a8a8a62001838565b604080516001600160a01b038881168252878116602083015281830184905291518285169286811692908b16917fb519c42fdb88f83f098814813f2ebff14fbf14f3e68b054e5a98834c69d54bfb9181900360600190a450505050505050565b3b151590565b60006060866001600160a01b0316633f84c12c60e01b8a8a898989604051602401808660048111156200186757fe5b8152602001856001600160a01b03168152602001846001600160a01b03168152602001836001600160a01b03168152602001826001600160a01b0316815260200195505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050506040518082805190602001908083835b60208310620019135780518252601f199092019160209182019101620018f2565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811462001977576040519150601f19603f3d011682016040523d82523d6000602084013e6200197c565b606091505b50915091508162001bc65782620019938a62001ea1565b826040516020018083805190602001908083835b60208310620019c85780518252601f199092019160209182019101620019a7565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831062001a125780518252601f199092019160209182019101620019f1565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529062001ad45760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101562001a9857818101518382015260200162001a7e565b50505050905090810190601f16801562001ac65780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50856001600160a01b0316876001600160a01b0316896001600160a01b03167fbf0ae6830883bd89855f2e7b17a2924b5de0b2b3d4a8834d7c2c0d5dc53447db848d8a8a604051808060200185600481111562001b2d57fe5b8152602001846001600160a01b03168152602001836001600160a01b03168152602001828103825286818151815260200191508051906020019080838360005b8381101562001b8757818101518382015260200162001b6d565b50505050905090810190601f16801562001bb55780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a45b505050505050505050565b604080516001600160a01b038881166024830152878116604483015285811660648301528481166084808401919091528351808403909101815260a490920183526020820180516001600160e01b031663df369ba760e01b17815292518251600094606094938a169392918291908083835b6020831062001c645780518252601f19909201916020918201910162001c43565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811462001cc8576040519150601f19603f3d011682016040523d82523d6000602084013e62001ccd565b606091505b50915091508162001e9757828160405160200180807f4d6967726174696f6e4f757443616e63656c486f6f6b3a20000000000000000081525060180182805190602001908083835b6020831062001d365780518252601f19909201916020918201910162001d15565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040529062001db95760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831562001a9857818101518382015260200162001a7e565b50856001600160a01b0316876001600160a01b0316896001600160a01b03167f7c79070aa51adb676fb9c8d0f7a1f841ff9cf514444b37c95297ed1c52547b328489896040518080602001846001600160a01b03168152602001836001600160a01b03168152602001828103825285818151815260200191508051906020019080838360005b8381101562001e5957818101518382015260200162001e3f565b50505050905090810190601f16801562001e875780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a45b5050505050505050565b6060600082600481111562001eb257fe5b141562001ef4575060408051808201909152601c81527f4d6967726174696f6e4f7574486f6f6b2e5072655369676e616c3a2000000000602082015262000c62565b600182600481111562001f0357fe5b141562001f45575060408051808201909152601d81527f4d6967726174696f6e4f7574486f6f6b2e506f73745369676e616c3a20000000602082015262000c62565b600282600481111562001f5457fe5b141562001f96575060408051808201909152601d81527f4d6967726174696f6e4f7574486f6f6b2e5072654d6967726174653a20000000602082015262000c62565b600382600481111562001fa557fe5b141562001fe7575060408051808201909152601e81527f4d6967726174696f6e4f7574486f6f6b2e506f73744d6967726174653a200000602082015262000c62565b600482600481111562001ff657fe5b141562002038575060408051808201909152601d81527f4d6967726174696f6e4f7574486f6f6b2e506f737443616e63656c3a20000000602082015262000c62565b505060408051602081019091526000815290565b6103c1806200211e83390190565b60408051608081018252600080825260208201819052918101829052606081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620020c45782800160ff19823516178555620020f4565b82800160010185558215620020f4579182015b82811115620020f4578235825591602001919060010190620020d7565b506200210292915062002106565b5090565b5b808211156200210257600081556001016200210756fe608060405234801561001057600080fd5b506040516103c13803806103c18339818101604052604081101561003357600080fd5b810190808051604051939291908464010000000082111561005357600080fd5b90830190602082018581111561006857600080fd5b825164010000000081118282018810171561008257600080fd5b82525081516020918201929091019080838360005b838110156100af578181015183820152602001610097565b50505050905090810190601f1680156100dc5780820380516001836020036101000a031916815260200191505b5060408181526020928301516352d1902d60e01b835290519094506001600160a01b03851693506352d1902d92600480840193919291829003018186803b15801561012657600080fd5b505afa15801561013a573d6000803e3d6000fd5b505050506040513d602081101561015057600080fd5b50517f027b9570e9fedc1a80b937ae9a06861e5faef3992491af30b684a64b3fbec7a5146101af5760405162461bcd60e51b815260040180806020018281038252602581526020018061039c6025913960400191505060405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5560006060826001600160a01b0316846040518082805190602001908083835b602083106102105780518252601f1990920191602091820191016101f1565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114610270576040519150601f19603f3d011682016040523d82523d6000602084013e610275565b606091505b50915091508181906103055760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156102ca5781810151838201526020016102b2565b50505050905090810190601f1680156102f75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50505050506084806103186000396000f3fe60806040527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc543660008037600080366000846127105a03f43d806000803e818015604957816000f35b816000fdfea2646970667358221220bbf55cdae3dc46d2a5e7b99766dd55ccf780257e97c67bd8075873f6748a939264736f6c634300060c0033636f6e7374727563746f723a205f7661756c744c6962206e6f7420636f6d70617469626c654f6e6c79207468652063757272656e742046756e644465706c6f7965722063616e2063616c6c20746869732066756e6374696f6e7369676e616c4d6967726174696f6e3a204e6f6e2d636f6e7472616374205f6e6578745661756c744163636573736f7273657443757272656e7446756e644465706c6f7965723a205f6e65787446756e644465706c6f79657220697320616c72656164792063757272656e7446756e644465706c6f79657263616e63656c4d6967726174696f6e3a204e6f206d6967726174696f6e20726571756573742065786973747373657443757272656e7446756e644465706c6f7965723a205f6e65787446756e644465706c6f7965722063616e6e6f7420626520656d70747963616e63656c4d6967726174696f6e3a204e6f7420616e20616c6c6f7765642063616c6c6572657865637574654d6967726174696f6e3a20546865207461726765742046756e644465706c6f796572206973206e6f206c6f6e676572207468652063757272656e742046756e644465706c6f7965724f6e6c792074686520636f6e7472616374206f776e65722063616e2063616c6c20746869732066756e6374696f6e72656d6f76654e6f6d696e617465644f776e65723a205468657265206973206e6f206e6f6d696e61746564206f776e65726465706c6f795661756c7450726f78793a204e6f6e2d636f6e7472616374205f7661756c744163636573736f727365744e6f6d696e617465644f776e65723a205f6e6578744e6f6d696e617465644f776e65722063616e6e6f7420626520656d7074797369676e616c4d6967726174696f6e3a205f7661756c7450726f787920646f6573206e6f74206578697374657865637574654d6967726174696f6e3a20546865206d6967726174696f6e2074696d656c6f636b20686173206e6f7420656c61707365647365744e6f6d696e617465644f776e65723a205f6e6578744e6f6d696e617465644f776e657220697320616c726561647920746865206f776e6572657865637574654d6967726174696f6e3a204f6e6c7920746865207461726765742046756e644465706c6f7965722063616e2063616c6c20746869732066756e6374696f6e7365744e6f6d696e617465644f776e65723a205f6e6578744e6f6d696e617465644f776e657220697320616c7265616479206e6f6d696e61746564636c61696d4f776e6572736869703a204f6e6c7920746865206e6f6d696e617465644f776e65722063616e2063616c6c20746869732066756e6374696f6e7369676e616c4d6967726174696f6e3a2043616e206f6e6c79206d69677261746520746f2061206e65772046756e644465706c6f79657273657443757272656e7446756e644465706c6f7965723a204e6f6e2d636f6e7472616374205f6e65787446756e644465706c6f796572657865637574654d6967726174696f6e3a204e6f206d6967726174696f6e20726571756573742065786973747320666f72205f7661756c7450726f78797365744d6967726174696f6e54696d656c6f636b3a205f6e65787454696d656c6f636b206973207468652063757272656e742074696d656c6f636ba2646970667358221220e993caff25de4ab3ce12bf915478eb7d06e871a51caa473040cfdfd73e5a7dee64736f6c634300060c0033

Deployed Bytecode

0x60806040523480156200001157600080fd5b5060043610620001485760003560e01c806377a8c62411620000bd57806397af7050116200007b57806397af7050146200042d5780639c9d48da1462000456578063b47b06001462000487578063d0449d3d1462000509578063d15f9b9c14620005325762000148565b806377a8c62414620003885780637c77b2ed14620003b15780637dad9fc814620003bb5780638156eecf1462000419578063893d20e814620004235762000148565b80633d7c74f8116200010b5780633d7c74f814620002795780634e71e0c814620002a257806366231cea14620002ac578063728e17a014620002e9578063757bc0dd14620003125762000148565b80631df419f7146200014d57806322a0c08b146200016f578063288b6a3614620002225780632fa0c161146200022c57806338b3eb1b1462000248575b600080fd5b6200016d600480360360208110156200016557600080fd5b503562000573565b005b62000206600480360360808110156200018757600080fd5b6001600160a01b0382358116926020810135821692604082013590921691810190608081016060820135640100000000811115620001c457600080fd5b820183602082011115620001d757600080fd5b80359060200191846001830284011164010000000083111715620001fa57600080fd5b50909250905062000646565b604080516001600160a01b039092168252519081900360200190f35b62000206620008df565b62000236620008ee565b60408051918252519081900360200190f35b6200016d600480360360408110156200026057600080fd5b506001600160a01b0381351690602001351515620008f4565b62000206600480360360208110156200029157600080fd5b50356001600160a01b031662000c46565b6200016d62000c67565b620002d560048036036020811015620002c457600080fd5b50356001600160a01b031662000d10565b604080519115158252519081900360200190f35b6200016d600480360360208110156200030157600080fd5b50356001600160a01b031662000d43565b6200016d600480360360208110156200032a57600080fd5b8101906020810181356401000000008111156200034657600080fd5b8201836020820111156200035957600080fd5b803590602001918460018302840111640100000000831117156200037c57600080fd5b50909250905062000ebd565b6200023660048036036020811015620003a057600080fd5b50356001600160a01b031662000f7b565b6200020662000fc4565b620003e460048036036020811015620003d357600080fd5b50356001600160a01b031662000fd3565b604080516001600160a01b03958616815293851660208501529190931682820152606082019290925290519081900360800190f35b6200016d6200106b565b6200020662001147565b6200016d600480360360208110156200044557600080fd5b50356001600160a01b031662001156565b6200016d600480360360408110156200046e57600080fd5b506001600160a01b0381351690602001351515620012e1565b620004916200152a565b6040805160208082528351818301528351919283929083019185019080838360005b83811015620004cd578181015183820152602001620004b3565b50505050905090810190601f168015620004fb5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b620002d5600480360360208110156200052157600080fd5b50356001600160a01b0316620015c4565b6200016d600480360360808110156200054a57600080fd5b506001600160a01b038135811691602081013582169160408201351690606001351515620015e4565b6002546001600160a01b03163314620005be5760405162461bcd60e51b815260040180806020018281038252602e81526020018062002665602e913960400191505060405180910390fd5b60035481811415620006025760405162461bcd60e51b815260040180806020018281038252603b8152602001806200292d603b913960400191505060405180910390fd5b6003829055604080518281526020810184905281517f481ce28a1145a5d9b59e2d1d7eba33bc3350124def8fdc91032238d343ad5361929181900390910190a15050565b600080546001600160a01b03163314620006925760405162461bcd60e51b8152600401808060200182810382526034815260200180620024df6034913960400191505060405180910390fd5b6200069d8462001832565b620006da5760405162461bcd60e51b815260040180806020018281038252602d815260200180620026c4602d913960400191505060405180910390fd5b6060635c9a6d3760e01b8686868660405160240180856001600160a01b03168152602001846001600160a01b0316815260200180602001828103825284848281815260200192508082843760008382015260408051601f909201601f1990811690940182810390940182529283526020810180516001600160e01b03166001600160e01b0319909b169a909a17909952505196975087968e965062000786955093506200204c92505050565b8080602001836001600160a01b03168152602001828103825284818151815260200191508051906020019080838360005b83811015620007d1578181015183820152602001620007b7565b50505050905090810190601f168015620007ff5780820380516001836020036101000a031916815260200191505b509350505050604051809103906000f08015801562000822573d6000803e3d6000fd5b506001600160a01b0380821660008181526005602090815260409182902080546001600160a01b0319163390811790915582519384528a85169184019190915260609183018281529183018890529395508a8316928a169184917fa50560b448ad796ef60adfeffe1c19ed34daf94c2aa6905d0e209017dbc19f589188918c918c918c919060808201848480828437600083820152604051601f909101601f191690920182900397509095505050505050a4505095945050505050565b6001546001600160a01b031690565b60035490565b620008fe6200205a565b506001600160a01b038083166000908152600660209081526040918290208251608081018452815485168082526001830154861693820193909352600282015490941692840192909252600390910154606083015280620009915760405162461bcd60e51b815260040180806020018281038252603d815260200180620028f0603d913960400191505060405180910390fd5b336001600160a01b03821614620009da5760405162461bcd60e51b8152600401808060200182810382526045815260200180620027c56045913960600191505060405180910390fd5b6000546001600160a01b0382811691161462000a285760405162461bcd60e51b815260040180806020018281038252604f81526020018062002616604f913960600191505060405180910390fd5b60608201514281111562000a6e5760405162461bcd60e51b8152600401808060200182810382526038815260200180620027526038913960400191505060405180910390fd5b6001600160a01b0380861660009081526005602090815260409182902054908601519186015192169162000aa9600289858886868d62001838565b876001600160a01b0316634140d607826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b15801562000af957600080fd5b505af115801562000b0e573d6000803e3d6000fd5b50505050876001600160a01b031663ab9253ac836040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b15801562000b6257600080fd5b505af115801562000b77573d6000803e3d6000fd5b5050506001600160a01b03808a1660009081526005602090815260408083208054948b166001600160a01b0319958616179055600690915281208054831681556001810180548416905560028101805490931690925560039182015562000be5915089858886868d62001838565b604080516001600160a01b038481168252838116602083015281830187905291518288169286811692908c16917fad6fb3d36e2cda148dfd43203c1a40c0da9a9baa662ae9d6c3b0c3e4a9d6a6359181900360600190a45050505050505050565b6001600160a01b03808216600090815260056020526040902054165b919050565b6001546001600160a01b031633811462000cb35760405162461bcd60e51b815260040180806020018281038252603e81526020018062002845603e913960400191505060405180910390fd5b600180546001600160a01b0319908116909155600280546001600160a01b0384811693821684179092556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038116600090815260066020526040812060030154801580159062000d3c5750804210155b9392505050565b6002546001600160a01b0316331462000d8e5760405162461bcd60e51b815260040180806020018281038252602e81526020018062002665602e913960400191505060405180910390fd5b6001600160a01b03811662000dd55760405162461bcd60e51b8152600401808060200182810382526036815260200180620026f16036913960400191505060405180910390fd5b6002546001600160a01b038281169116141562000e245760405162461bcd60e51b815260040180806020018281038252603b8152602001806200278a603b913960400191505060405180910390fd5b6001546001600160a01b038281169116141562000e735760405162461bcd60e51b815260040180806020018281038252603b8152602001806200280a603b913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f132c19de901bb4ed8403c34734b6c841d5dc57745824da452a52433519ea5abf90600090a250565b6002546001600160a01b0316331462000f085760405162461bcd60e51b815260040180806020018281038252602e81526020018062002665602e913960400191505060405180910390fd5b62000f166004838362002081565b507ff0115712c23b609855a28d7b8963c6d16d732ae388b11e5d4ec6d5eae4ad8698828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6001600160a01b0381166000908152600660205260408120600301548062000fa857600091505062000c62565b80421062000fbb57600091505062000c62565b42900392915050565b6000546001600160a01b031690565b60008060008062000fe36200205a565b506001600160a01b038086166000908152600660209081526040918290208251608081018452815485168152600182015485169281019290925260028101549093169181019190915260039091015460608201819052156200106257806000015181602001518260400151836060015194509450945094505062001064565b505b9193509193565b6002546001600160a01b03163314620010b65760405162461bcd60e51b815260040180806020018281038252602e81526020018062002665602e913960400191505060405180910390fd5b6001546001600160a01b031680620011005760405162461bcd60e51b8152600401808060200182810382526031815260200180620026936031913960400191505060405180910390fd5b600180546001600160a01b03191690556040516001600160a01b038216907fe4136584a5e8bb85d66301f3ce8b11cc2e5a8bea3979f10ea2451353849acc4790600090a250565b6002546001600160a01b031690565b6002546001600160a01b03163314620011a15760405162461bcd60e51b815260040180806020018281038252602e81526020018062002665602e913960400191505060405180910390fd5b6001600160a01b038116620011e85760405162461bcd60e51b8152600401808060200182810382526039815260200180620025b76039913960400191505060405180910390fd5b620011f38162001832565b620012305760405162461bcd60e51b8152600401808060200182810382526036815260200180620028ba6036913960400191505060405180910390fd5b6000546001600160a01b03908116908216811415620012815760405162461bcd60e51b8152600401808060200182810382526048815260200180620025436048913960600191505060405180910390fd5b600080546001600160a01b0319166001600160a01b03848116918217909255604080519284168352602083019190915280517f44cf34a26ccbaa8a20e6098a1278e28682572ec9921eb43d8dab274a503e92f59281900390910190a15050565b620012eb6200205a565b506001600160a01b0380831660009081526006602090815260409182902082516080810184528154851680825260018301548616938201939093526002820154909416928401929092526003909101546060830152806200137e5760405162461bcd60e51b815260040180806020018281038252602c8152602001806200258b602c913960400191505060405180910390fd5b336001600160a01b038216148062001407575060408051633ef03e7560e11b815233600482015290516001600160a01b03861691637de07cea916024808301926020929190829003018186803b158015620013d857600080fd5b505afa158015620013ed573d6000803e3d6000fd5b505050506040513d60208110156200140457600080fd5b50515b620014445760405162461bcd60e51b8152600401808060200182810382526026815260200180620025f06026913960400191505060405180910390fd5b6001600160a01b0380851660009081526005602090815260408083205486830151878301516060890151600690955292852080546001600160a01b03199081168255600182018054821690556002820180549091169055600301949094559093169290620014b9600489868887878d62001838565b620014c988858786868c62001bd1565b604080516001600160a01b038581168252848116602083015281830184905291518288169287811692908c16917f9851a8f232c380eb2c1065756776e37d85d4fe0c8cb4005b0d72c749bfef923e9181900360600190a45050505050505050565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620015ba5780601f106200158e57610100808354040283529160200191620015ba565b820191906000526020600020905b8154815290600101906020018083116200159c57829003601f168201915b5050505050905090565b6001600160a01b0316600090815260066020526040902060030154151590565b6000546001600160a01b031633146200162f5760405162461bcd60e51b8152600401808060200182810382526034815260200180620024df6034913960400191505060405180910390fd5b6200163a8362001832565b620016775760405162461bcd60e51b8152600401808060200182810382526030815260200180620025136030913960400191505060405180910390fd5b6001600160a01b038085166000908152600560205260409020541680620016d05760405162461bcd60e51b815260040180806020018281038252602b81526020018062002727602b913960400191505060405180910390fd5b336001600160a01b0382168114156200171b5760405162461bcd60e51b8152600401808060200182810382526037815260200180620028836037913960400191505060405180910390fd5b6200172d600087848489898962001838565b60038054604080516080810182526001600160a01b03808616825289811660208084019182528a831684860190815242909601606085018181528e85166000908152600690935295909120935184549084166001600160a01b0319918216178555915160018086018054928616928516929092179091559551600285018054919094169216919091179091559151930192909255620017d2908885858a8a8a62001838565b604080516001600160a01b038881168252878116602083015281830184905291518285169286811692908b16917fb519c42fdb88f83f098814813f2ebff14fbf14f3e68b054e5a98834c69d54bfb9181900360600190a450505050505050565b3b151590565b60006060866001600160a01b0316633f84c12c60e01b8a8a898989604051602401808660048111156200186757fe5b8152602001856001600160a01b03168152602001846001600160a01b03168152602001836001600160a01b03168152602001826001600160a01b0316815260200195505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050506040518082805190602001908083835b60208310620019135780518252601f199092019160209182019101620018f2565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811462001977576040519150601f19603f3d011682016040523d82523d6000602084013e6200197c565b606091505b50915091508162001bc65782620019938a62001ea1565b826040516020018083805190602001908083835b60208310620019c85780518252601f199092019160209182019101620019a7565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831062001a125780518252601f199092019160209182019101620019f1565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529062001ad45760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101562001a9857818101518382015260200162001a7e565b50505050905090810190601f16801562001ac65780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50856001600160a01b0316876001600160a01b0316896001600160a01b03167fbf0ae6830883bd89855f2e7b17a2924b5de0b2b3d4a8834d7c2c0d5dc53447db848d8a8a604051808060200185600481111562001b2d57fe5b8152602001846001600160a01b03168152602001836001600160a01b03168152602001828103825286818151815260200191508051906020019080838360005b8381101562001b8757818101518382015260200162001b6d565b50505050905090810190601f16801562001bb55780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a45b505050505050505050565b604080516001600160a01b038881166024830152878116604483015285811660648301528481166084808401919091528351808403909101815260a490920183526020820180516001600160e01b031663df369ba760e01b17815292518251600094606094938a169392918291908083835b6020831062001c645780518252601f19909201916020918201910162001c43565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811462001cc8576040519150601f19603f3d011682016040523d82523d6000602084013e62001ccd565b606091505b50915091508162001e9757828160405160200180807f4d6967726174696f6e4f757443616e63656c486f6f6b3a20000000000000000081525060180182805190602001908083835b6020831062001d365780518252601f19909201916020918201910162001d15565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040529062001db95760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831562001a9857818101518382015260200162001a7e565b50856001600160a01b0316876001600160a01b0316896001600160a01b03167f7c79070aa51adb676fb9c8d0f7a1f841ff9cf514444b37c95297ed1c52547b328489896040518080602001846001600160a01b03168152602001836001600160a01b03168152602001828103825285818151815260200191508051906020019080838360005b8381101562001e5957818101518382015260200162001e3f565b50505050905090810190601f16801562001e875780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a45b5050505050505050565b6060600082600481111562001eb257fe5b141562001ef4575060408051808201909152601c81527f4d6967726174696f6e4f7574486f6f6b2e5072655369676e616c3a2000000000602082015262000c62565b600182600481111562001f0357fe5b141562001f45575060408051808201909152601d81527f4d6967726174696f6e4f7574486f6f6b2e506f73745369676e616c3a20000000602082015262000c62565b600282600481111562001f5457fe5b141562001f96575060408051808201909152601d81527f4d6967726174696f6e4f7574486f6f6b2e5072654d6967726174653a20000000602082015262000c62565b600382600481111562001fa557fe5b141562001fe7575060408051808201909152601e81527f4d6967726174696f6e4f7574486f6f6b2e506f73744d6967726174653a200000602082015262000c62565b600482600481111562001ff657fe5b141562002038575060408051808201909152601d81527f4d6967726174696f6e4f7574486f6f6b2e506f737443616e63656c3a20000000602082015262000c62565b505060408051602081019091526000815290565b6103c1806200211e83390190565b60408051608081018252600080825260208201819052918101829052606081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620020c45782800160ff19823516178555620020f4565b82800160010185558215620020f4579182015b82811115620020f4578235825591602001919060010190620020d7565b506200210292915062002106565b5090565b5b808211156200210257600081556001016200210756fe608060405234801561001057600080fd5b506040516103c13803806103c18339818101604052604081101561003357600080fd5b810190808051604051939291908464010000000082111561005357600080fd5b90830190602082018581111561006857600080fd5b825164010000000081118282018810171561008257600080fd5b82525081516020918201929091019080838360005b838110156100af578181015183820152602001610097565b50505050905090810190601f1680156100dc5780820380516001836020036101000a031916815260200191505b5060408181526020928301516352d1902d60e01b835290519094506001600160a01b03851693506352d1902d92600480840193919291829003018186803b15801561012657600080fd5b505afa15801561013a573d6000803e3d6000fd5b505050506040513d602081101561015057600080fd5b50517f027b9570e9fedc1a80b937ae9a06861e5faef3992491af30b684a64b3fbec7a5146101af5760405162461bcd60e51b815260040180806020018281038252602581526020018061039c6025913960400191505060405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5560006060826001600160a01b0316846040518082805190602001908083835b602083106102105780518252601f1990920191602091820191016101f1565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114610270576040519150601f19603f3d011682016040523d82523d6000602084013e610275565b606091505b50915091508181906103055760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156102ca5781810151838201526020016102b2565b50505050905090810190601f1680156102f75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50505050506084806103186000396000f3fe60806040527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc543660008037600080366000846127105a03f43d806000803e818015604957816000f35b816000fdfea2646970667358221220bbf55cdae3dc46d2a5e7b99766dd55ccf780257e97c67bd8075873f6748a939264736f6c634300060c0033636f6e7374727563746f723a205f7661756c744c6962206e6f7420636f6d70617469626c654f6e6c79207468652063757272656e742046756e644465706c6f7965722063616e2063616c6c20746869732066756e6374696f6e7369676e616c4d6967726174696f6e3a204e6f6e2d636f6e7472616374205f6e6578745661756c744163636573736f7273657443757272656e7446756e644465706c6f7965723a205f6e65787446756e644465706c6f79657220697320616c72656164792063757272656e7446756e644465706c6f79657263616e63656c4d6967726174696f6e3a204e6f206d6967726174696f6e20726571756573742065786973747373657443757272656e7446756e644465706c6f7965723a205f6e65787446756e644465706c6f7965722063616e6e6f7420626520656d70747963616e63656c4d6967726174696f6e3a204e6f7420616e20616c6c6f7765642063616c6c6572657865637574654d6967726174696f6e3a20546865207461726765742046756e644465706c6f796572206973206e6f206c6f6e676572207468652063757272656e742046756e644465706c6f7965724f6e6c792074686520636f6e7472616374206f776e65722063616e2063616c6c20746869732066756e6374696f6e72656d6f76654e6f6d696e617465644f776e65723a205468657265206973206e6f206e6f6d696e61746564206f776e65726465706c6f795661756c7450726f78793a204e6f6e2d636f6e7472616374205f7661756c744163636573736f727365744e6f6d696e617465644f776e65723a205f6e6578744e6f6d696e617465644f776e65722063616e6e6f7420626520656d7074797369676e616c4d6967726174696f6e3a205f7661756c7450726f787920646f6573206e6f74206578697374657865637574654d6967726174696f6e3a20546865206d6967726174696f6e2074696d656c6f636b20686173206e6f7420656c61707365647365744e6f6d696e617465644f776e65723a205f6e6578744e6f6d696e617465644f776e657220697320616c726561647920746865206f776e6572657865637574654d6967726174696f6e3a204f6e6c7920746865207461726765742046756e644465706c6f7965722063616e2063616c6c20746869732066756e6374696f6e7365744e6f6d696e617465644f776e65723a205f6e6578744e6f6d696e617465644f776e657220697320616c7265616479206e6f6d696e61746564636c61696d4f776e6572736869703a204f6e6c7920746865206e6f6d696e617465644f776e65722063616e2063616c6c20746869732066756e6374696f6e7369676e616c4d6967726174696f6e3a2043616e206f6e6c79206d69677261746520746f2061206e65772046756e644465706c6f79657273657443757272656e7446756e644465706c6f7965723a204e6f6e2d636f6e7472616374205f6e65787446756e644465706c6f796572657865637574654d6967726174696f6e3a204e6f206d6967726174696f6e20726571756573742065786973747320666f72205f7661756c7450726f78797365744d6967726174696f6e54696d656c6f636b3a205f6e65787454696d656c6f636b206973207468652063757272656e742074696d656c6f636ba2646970667358221220e993caff25de4ab3ce12bf915478eb7d06e871a51caa473040cfdfd73e5a7dee64736f6c634300060c0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.