ETH Price: $3,100.32 (+1.09%)
Gas: 9 Gwei

Contract

0x101500214981e7A5Ad2334D8404eaF365C2c3113
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
0x60806040136278212021-11-16 17:09:37885 days ago1637082577IN
 Create: L1StandardBridge
0 ETH0.3386787133.62926702

Advanced mode:
Parent Transaction Hash Block From To Value
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
L1StandardBridge

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion
File 1 of 14 : L1StandardBridge.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

/* Interface Imports */
import { IL1StandardBridge } from "./IL1StandardBridge.sol";
import { IL1ERC20Bridge } from "./IL1ERC20Bridge.sol";
import { IL2ERC20Bridge } from "../../L2/messaging/IL2ERC20Bridge.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/* Library Imports */
import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { iMVM_DiscountOracle } from "../../MVM/iMVM_DiscountOracle.sol";
import { Lib_AddressManager } from "../../libraries/resolver/Lib_AddressManager.sol";

/**
 * @title L1StandardBridge
 * @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard
 * tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits
 * and listening to it for newly finalized withdrawals.
 *
 * Runtime target: EVM
 */
contract L1StandardBridge is IL1StandardBridge, CrossDomainEnabled {
    using SafeERC20 for IERC20;

    /********************************
     * External Contract References *
     ********************************/

    address public l2TokenBridge;
    address public metis;
    address public addressmgr;

    // Maps L1 token to chainid to L2 token to balance of the L1 token deposited
    mapping(address => mapping (uint256 => mapping (address => uint256))) public deposits;

    
    uint256 constant public DEFAULT_CHAINID = 1088;

    /***************
     * Constructor *
     ***************/

    // This contract lives behind a proxy, so the constructor parameters will go unused.
    constructor() CrossDomainEnabled(address(0)) {}

    /******************
     * Initialization *
     ******************/

    /**
     * @param _l1messenger L1 Messenger address being used for cross-chain communications.
     * @param _l2TokenBridge L2 standard bridge address.
     */
    function initialize(
        address _l1messenger,
        address _l2TokenBridge,
        address _metis,
        address _addressmgr
    )
        public
    {
        require(messenger == address(0), "Contract has already been initialized.");
        messenger = _l1messenger;
        l2TokenBridge = _l2TokenBridge;
        metis = _metis;
        addressmgr = _addressmgr;
    }

    /**************
     * Depositing *
     **************/

    /** @dev Modifier requiring sender to be EOA.  This check could be bypassed by a malicious
     *  contract via initcode, but it takes care of the user error we want to avoid.
     */
    modifier onlyEOA() {
        // Used to stop deposits from contracts (avoid accidentally lost tokens)
        require(!Address.isContract(msg.sender), "Account not EOA");
        _;
    }

    /**
     * @dev do not accept no data call
     */
    //receive() external payable onlyEOA {
    //    _initiateETHDeposit(msg.sender, msg.sender, 200_000, bytes(""));
    //}

    /**
     * @inheritdoc IL1StandardBridge
     */
    function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA {
        _initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data);
    }
    
    function depositETHByChainId(
        uint256 _chainId,
        uint32 _l2Gas,
        bytes calldata _data
    )
        external
        override
        payable
        onlyEOA()
    {
        _initiateETHDepositByChainId(
            _chainId,
            msg.sender,
            msg.sender,
            _l2Gas,
            _data
        );
    }

    /**
     * @inheritdoc IL1StandardBridge
     */
    function depositETHTo(
        address _to,
        uint32 _l2Gas,
        bytes calldata _data
    ) external payable {
        _initiateETHDeposit(msg.sender, _to, _l2Gas, _data);
    }
    
    function depositETHToByChainId(
        uint256 _chainId,
        address _to,
        uint32 _l2Gas,
        bytes calldata _data
    )
        external
        override
        payable
    {
        _initiateETHDepositByChainId(
            _chainId,
            msg.sender,
            _to,
            _l2Gas,
            _data
        );
    }

    /**
     * @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of
     * the deposit.
     * @param _from Account to pull the deposit from on L1.
     * @param _to Account to give the deposit to on L2.
     * @param _l2Gas Gas limit required to complete the deposit on L2.
     * @param _data Optional data to forward to L2. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function _initiateETHDeposit(
        address _from,
        address _to,
        uint32 _l2Gas,
        bytes memory _data
    ) internal {
        _initiateETHDepositByChainId(DEFAULT_CHAINID, _from, _to, _l2Gas, _data);
    }
    
    function _initiateETHDepositByChainId(
        uint256 _chainId,
        address _from,
        address _to,
        uint32 _l2Gas,
        bytes memory _data
    )
        internal
    {
    
        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(Lib_AddressManager(addressmgr).getAddress('MVM_DiscountOracle'));
        uint32 mingas = uint32(oracle.getMinL2Gas());
        if (_l2Gas < mingas) {
            _l2Gas = mingas;
        }
        uint256 fee = _l2Gas * oracle.getDiscount();
        
        require(fee <= msg.value, string(abi.encodePacked("insufficient fee supplied. send at least ", uint2str(fee))));
        // Construct calldata for finalizeDeposit call
        bytes memory message =
            abi.encodeWithSelector(
                IL2ERC20Bridge.finalizeDeposit.selector,
                address(0),
                Lib_PredeployAddresses.OVM_ETH,
                _from,
                _to,
                msg.value - fee,
                _data
            );
        
        // Send calldata into L2
        sendCrossDomainMessageViaChainId(
            _chainId,
            l2TokenBridge,
            _l2Gas,
            message,
            fee  // only send the supplied fees over (obviously)
        );

        emit ETHDepositInitiated(_from, _to, msg.value, _data, _chainId);
    }

    /**
     * @inheritdoc IL1ERC20Bridge
     */
    function depositERC20(
        address _l1Token,
        address _l2Token,
        uint256 _amount,
        uint32 _l2Gas,
        bytes calldata _data
    ) external virtual onlyEOA {
        _initiateERC20DepositByChainId(DEFAULT_CHAINID, _l1Token, _l2Token, msg.sender, msg.sender, _amount, _l2Gas, _data);
    }

    /**
     * @inheritdoc IL1ERC20Bridge
     */
    function depositERC20To(
        address _l1Token,
        address _l2Token,
        address _to,
        uint256 _amount,
        uint32 _l2Gas,
        bytes calldata _data
    ) external virtual {
        _initiateERC20DepositByChainId(DEFAULT_CHAINID, _l1Token, _l2Token, msg.sender, _to, _amount, _l2Gas, _data);
    }
    function depositERC20ByChainId(
        uint256 _chainid,
        address _l1Token,
        address _l2Token,
        uint256 _amount,
        uint32 _l2Gas,
        bytes calldata _data
    )
        external
        override
        virtual
        payable
        onlyEOA()
    {
        _initiateERC20DepositByChainId(_chainid, _l1Token, _l2Token, msg.sender, msg.sender, _amount, _l2Gas, _data);
    }
    
    function depositERC20ToByChainId(
        uint256 _chainid,
        address _l1Token,
        address _l2Token,
        address _to,
        uint256 _amount,
        uint32 _l2Gas,
        bytes calldata _data
    )
        external
        override
        payable
        virtual
    {
        _initiateERC20DepositByChainId(_chainid, _l1Token, _l2Token, msg.sender, _to, _amount, _l2Gas, _data);
    }

    /**
     * @dev Performs the logic for deposits by informing the L2 Deposited Token
     * contract of the deposit and calling a handler to lock the L1 funds. (e.g. transferFrom)
     *
     * @param _l1Token Address of the L1 ERC20 we are depositing
     * @param _l2Token Address of the L1 respective L2 ERC20
     * @param _from Account to pull the deposit from on L1
     * @param _to Account to give the deposit to on L2
     * @param _amount Amount of the ERC20 to deposit.
     * @param _l2Gas Gas limit required to complete the deposit on L2.
     * @param _data Optional data to forward to L2. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function _initiateERC20Deposit(
        address _l1Token,
        address _l2Token,
        address _from,
        address _to,
        uint256 _amount,
        uint32 _l2Gas,
        bytes calldata _data
    ) internal {
        _initiateERC20DepositByChainId(DEFAULT_CHAINID, _l1Token, _l2Token, _from, _to, _amount, _l2Gas, _data);
    }
    
    function _initiateERC20DepositByChainId(
        uint256 _chainId,
        address _l1Token,
        address _l2Token,
        address _from,
        address _to,
        uint256 _amount,
        uint32 _l2Gas,
        bytes calldata _data
    )
        internal
    {
        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(Lib_AddressManager(addressmgr).getAddress('MVM_DiscountOracle'));
        
        // stack too deep. so no more local variables
        if (_l2Gas < uint32(oracle.getMinL2Gas())) {
            _l2Gas = uint32(oracle.getMinL2Gas());
        }
        
        require(_l2Gas * oracle.getDiscount() <= msg.value, 
                string(abi.encodePacked("insufficient fee supplied. send at least ", uint2str(_l2Gas * oracle.getDiscount()))));
        
        // When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future
        // withdrawals. safeTransferFrom also checks if the contract has code, so this will fail if
        // _from is an EOA or address(0).
        IERC20(_l1Token).safeTransferFrom(
            _from,
            address(this),
            _amount
        );
        
        bytes memory message;
        if (_l1Token == metis) {
            // Construct calldata for finalizeDeposit call
          _l2Token = Lib_PredeployAddresses.MVM_COINBASE;
          message =
            abi.encodeWithSelector(
                IL2ERC20Bridge.finalizeDeposit.selector,
                address(0),
                Lib_PredeployAddresses.MVM_COINBASE,
                _from,
                _to,
                _amount,
                _data
            );
            
        } else {
          // Construct calldata for finalizeDeposit call
          message =
            abi.encodeWithSelector(
                IL2ERC20Bridge.finalizeDeposit.selector,
                _l1Token,
                _l2Token,
                _from,
                _to,
                _amount,
                _data
            );
        }

        // Send calldata into L2
        sendCrossDomainMessageViaChainId(
            _chainId,
            l2TokenBridge,
            _l2Gas,
            message,
            msg.value  //send all values as fees to cover l2 tx cost
        );
        
        deposits[_l1Token][_chainId][_l2Token] = deposits[_l1Token][_chainId][_l2Token] + (_amount);

        emit ERC20ChainID(_chainId);
        emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data);
        
    }

    /*************************
     * Cross-chain Functions *
     *************************/

    /**
     * @inheritdoc IL1StandardBridge
     */
    function finalizeETHWithdrawal(
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    ) external onlyFromCrossDomainAccount(l2TokenBridge) {
        (bool success, ) = _to.call{ value: _amount }(new bytes(0));
        require(success, "TransferHelper::safeTransferETH: ETH transfer failed");

        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, DEFAULT_CHAINID);
    }
    
    function finalizeETHWithdrawalByChainId(
        uint256 _chainid,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    )
        external
        override
        onlyFromCrossDomainAccount(l2TokenBridge)
    {
        (bool success, ) = _to.call{value: _amount}(new bytes(0));
        require(success, "TransferHelper::safeTransferETH: ETH transfer failed");

        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, _chainid);
    }
    
    function finalizeMetisWithdrawalByChainId(
        uint256 _chainid,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    )
        external
        override
        onlyFromCrossDomainAccount(l2TokenBridge)
    {
        _finalizeERC20WithdrawalByChainId(_chainid, metis, Lib_PredeployAddresses.MVM_COINBASE, _from, _to, _amount, _data);
    }

    /**
     * @inheritdoc IL1ERC20Bridge
     */
    function finalizeERC20Withdrawal(
        address _l1Token,
        address _l2Token,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    ) external onlyFromCrossDomainAccount(l2TokenBridge) {
        _finalizeERC20WithdrawalByChainId(DEFAULT_CHAINID, _l1Token, _l2Token, _from, _to, _amount, _data);
    }
    
    function finalizeERC20WithdrawalByChainId(
        uint256 _chainid,
        address _l1Token,
        address _l2Token,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    )
        external
        override
        onlyFromCrossDomainAccount(l2TokenBridge)
    {
        _finalizeERC20WithdrawalByChainId(_chainid, _l1Token, _l2Token, _from, _to, _amount, _data);
    }
    
    function _finalizeERC20WithdrawalByChainId(
        uint256 _chainid,
        address _l1Token,
        address _l2Token,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    )
        internal
    {
        deposits[_l1Token][_chainid][_l2Token] = deposits[_l1Token][_chainid][_l2Token] - _amount;

        // When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer
        IERC20(_l1Token).safeTransfer(_to, _amount);

        emit ERC20ChainID(_chainid);
        emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);
        
    }

    /*****************************
     * Temporary - Migrating ETH *
     *****************************/

    /**
     * @dev Adds ETH balance to the account. This is meant to allow for ETH
     * to be migrated from an old gateway to a new gateway.
     * NOTE: This is left for one upgrade only so we are able to receive the migrated ETH from the
     * old contract
     */
    function donateETH() external payable {}
    
    function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
        if (_i == 0) {
            return "0";
        }
        uint j = _i;
        uint len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint k = len;
        while (_i != 0) {
            k = k-1;
            uint8 temp = (48 + uint8(_i - _i / 10 * 10));
            bytes1 b1 = bytes1(temp);
            bstr[k] = b1;
            _i /= 10;
        }
        return string(bstr);
    }
}

File 3 of 14 : IL1StandardBridge.sol
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;

import "./IL1ERC20Bridge.sol";

/**
 * @title IL1StandardBridge
 */
interface IL1StandardBridge is IL1ERC20Bridge {
    /**********
     * Events *
     **********/
    event ETHDepositInitiated(
        address indexed _from,
        address indexed _to,
        uint256 _amount,
        bytes _data,
        uint256 chainId
    );

    event ETHWithdrawalFinalized(
        address indexed _from,
        address indexed _to,
        uint256 _amount,
        bytes _data,
        uint256 chainId
    );

    /********************
     * Public Functions *
     ********************/

    /**
     * @dev Deposit an amount of the ETH to the caller's balance on L2.
     * @param _l2Gas Gas limit required to complete the deposit on L2.
     * @param _data Optional data to forward to L2. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function depositETH(uint32 _l2Gas, bytes calldata _data) external payable;

    /**
     * @dev Deposit an amount of ETH to a recipient's balance on L2.
     * @param _to L2 address to credit the withdrawal to.
     * @param _l2Gas Gas limit required to complete the deposit on L2.
     * @param _data Optional data to forward to L2. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function depositETHTo(
        address _to,
        uint32 _l2Gas,
        bytes calldata _data
    ) external payable;
    
    
    function depositETHByChainId (
        uint256 _chainId,
        uint32 _l2Gas,
        bytes calldata _data
    )
        external
        payable;
        
    function depositETHToByChainId (
        uint256 _chainId,
        address _to,
        uint32 _l2Gas,
        bytes calldata _data
    )
        external
        payable;

    /*************************
     * Cross-chain Functions *
     *************************/

    /**
     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the
     * L1 ETH token. Since only the xDomainMessenger can call this function, it will never be called
     * before the withdrawal is finalized.
     * @param _from L2 address initiating the transfer.
     * @param _to L1 address to credit the withdrawal to.
     * @param _amount Amount of the ERC20 to deposit.
     * @param _data Optional data to forward to L2. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function finalizeETHWithdrawal(
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    ) external;
    
    function finalizeETHWithdrawalByChainId (
        uint256 _chainId,
        address _from,
        address _to,
        uint _amount,
        bytes calldata _data
    )
        external;
}

File 4 of 14 : IL1ERC20Bridge.sol
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;

/**
 * @title IL1ERC20Bridge
 */
interface IL1ERC20Bridge {
    /**********
     * Events *
     **********/

    event ERC20DepositInitiated(
        address indexed _l1Token,
        address indexed _l2Token,
        address indexed _from,
        address _to,
        uint256 _amount,
        bytes _data
    );

    event ERC20WithdrawalFinalized(
        address indexed _l1Token,
        address indexed _l2Token,
        address indexed _from,
        address _to,
        uint256 _amount,
        bytes _data
    );

    event ERC20ChainID(uint256 _chainid);
    
    /********************
     * Public Functions *
     ********************/

    /**
     * @dev get the address of the corresponding L2 bridge contract.
     * @return Address of the corresponding L2 bridge contract.
     */
    function l2TokenBridge() external returns (address);

    /**
     * @dev deposit an amount of the ERC20 to the caller's balance on L2.
     * @param _l1Token Address of the L1 ERC20 we are depositing
     * @param _l2Token Address of the L1 respective L2 ERC20
     * @param _amount Amount of the ERC20 to deposit
     * @param _l2Gas Gas limit required to complete the deposit on L2.
     * @param _data Optional data to forward to L2. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function depositERC20(
        address _l1Token,
        address _l2Token,
        uint256 _amount,
        uint32 _l2Gas,
        bytes calldata _data
    ) external;

    /**
     * @dev deposit an amount of ERC20 to a recipient's balance on L2.
     * @param _l1Token Address of the L1 ERC20 we are depositing
     * @param _l2Token Address of the L1 respective L2 ERC20
     * @param _to L2 address to credit the withdrawal to.
     * @param _amount Amount of the ERC20 to deposit.
     * @param _l2Gas Gas limit required to complete the deposit on L2.
     * @param _data Optional data to forward to L2. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function depositERC20To(
        address _l1Token,
        address _l2Token,
        address _to,
        uint256 _amount,
        uint32 _l2Gas,
        bytes calldata _data
    ) external;
    
    /**
     * @dev deposit an amount of the ERC20 to the caller's balance on L2.
     * @param _chainid chainid
     * @param _l1Token Address of the L1 ERC20 we are depositing
     * @param _l2Token Address of the L1 respective L2 ERC20
     * @param _amount Amount of the ERC20 to deposit
     * @param _l2Gas Gas limit required to complete the deposit on L2.
     * @param _data Optional data to forward to L2. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function depositERC20ByChainId (
        uint256 _chainid,
        address _l1Token,
        address _l2Token,
        uint _amount,
        uint32 _l2Gas,
        bytes calldata _data
    )
        external payable;

    /**
     * @dev deposit an amount of ERC20 to a recipient's balance on L2.
     * @param _chainid chainid
     * @param _l1Token Address of the L1 ERC20 we are depositing
     * @param _l2Token Address of the L1 respective L2 ERC20
     * @param _to L2 address to credit the withdrawal to.
     * @param _amount Amount of the ERC20 to deposit.
     * @param _l2Gas Gas limit required to complete the deposit on L2.
     * @param _data Optional data to forward to L2. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function depositERC20ToByChainId (
        uint256 _chainid,
        address _l1Token,
        address _l2Token,
        address _to,
        uint _amount,
        uint32 _l2Gas,
        bytes calldata _data
    )
        external payable;
    /*************************
     * Cross-chain Functions *
     *************************/

    /**
     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the
     * L1 ERC20 token.
     * This call will fail if the initialized withdrawal from L2 has not been finalized.
     *
     * @param _l1Token Address of L1 token to finalizeWithdrawal for.
     * @param _l2Token Address of L2 token where withdrawal was initiated.
     * @param _from L2 address initiating the transfer.
     * @param _to L1 address to credit the withdrawal to.
     * @param _amount Amount of the ERC20 to deposit.
     * @param _data Data provided by the sender on L2. This data is provided
     *   solely as a convenience for external contracts. Aside from enforcing a maximum
     *   length, these contracts provide no guarantees about its content.
     */
    function finalizeERC20Withdrawal(
        address _l1Token,
        address _l2Token,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    ) external;
    
    /**
     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the
     * L1 ERC20 token.
     * This call will fail if the initialized withdrawal from L2 has not been finalized.
     *
     * @param _chainid chainid
     * @param _l1Token Address of L1 token to finalizeWithdrawal for.
     * @param _l2Token Address of L2 token where withdrawal was initiated.
     * @param _from L2 address initiating the transfer.
     * @param _to L1 address to credit the withdrawal to.
     * @param _amount Amount of the ERC20 to deposit.
     * @param _data Data provided by the sender on L2. This data is provided
     *   solely as a convenience for external contracts. Aside from enforcing a maximum
     *   length, these contracts provide no guarantees about its content.
     */    
     function finalizeERC20WithdrawalByChainId (
        uint256 _chainid,
        address _l1Token,
        address _l2Token,
        address _from,
        address _to,
        uint _amount,
        bytes calldata _data
    )
        external;
    /**
     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the
     * L1 ERC20 token.
     * This call will fail if the initialized withdrawal from L2 has not been finalized.
     *
     * @param _chainid chainid
     * @param _from L2 address initiating the transfer.
     * @param _to L1 address to credit the withdrawal to.
     * @param _amount Amount of the ERC20 to deposit.
     * @param _data Data provided by the sender on L2. This data is provided
     *   solely as a convenience for external contracts. Aside from enforcing a maximum
     *   length, these contracts provide no guarantees about its content.
     */    
    function finalizeMetisWithdrawalByChainId (
        uint256 _chainid,
        address _from,
        address _to,
        uint _amount,
        bytes calldata _data
    )
        external;
}

File 5 of 14 : IL2ERC20Bridge.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

/**
 * @title IL2ERC20Bridge
 */
interface IL2ERC20Bridge {
    /**********
     * Events *
     **********/

    event WithdrawalInitiated(
        address indexed _l1Token,
        address indexed _l2Token,
        address indexed _from,
        address _to,
        uint256 _amount,
        bytes _data
    );

    event DepositFinalized(
        address indexed _l1Token,
        address indexed _l2Token,
        address indexed _from,
        address _to,
        uint256 _amount,
        bytes _data
    );

    event DepositFailed(
        address indexed _l1Token,
        address indexed _l2Token,
        address indexed _from,
        address _to,
        uint256 _amount,
        bytes _data
    );

    /********************
     * Public Functions *
     ********************/

    /**
     * @dev get the address of the corresponding L1 bridge contract.
     * @return Address of the corresponding L1 bridge contract.
     */
    function l1TokenBridge() external returns (address);

    /**
     * @dev initiate a withdraw of some tokens to the caller's account on L1
     * @param _l2Token Address of L2 token where withdrawal was initiated.
     * @param _amount Amount of the token to withdraw.
     * param _l1Gas Unused, but included for potential forward compatibility considerations.
     * @param _data Optional data to forward to L1. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function withdraw(
        address _l2Token,
        uint256 _amount,
        uint32 _l1Gas,
        bytes calldata _data
    ) external payable;

    /**
     * @dev initiate a withdraw of some token to a recipient's account on L1.
     * @param _l2Token Address of L2 token where withdrawal is initiated.
     * @param _to L1 adress to credit the withdrawal to.
     * @param _amount Amount of the token to withdraw.
     * param _l1Gas Unused, but included for potential forward compatibility considerations.
     * @param _data Optional data to forward to L1. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function withdrawTo(
        address _l2Token,
        address _to,
        uint256 _amount,
        uint32 _l1Gas,
        bytes calldata _data
    ) external payable;

    /*************************
     * Cross-chain Functions *
     *************************/

    /**
     * @dev Complete a deposit from L1 to L2, and credits funds to the recipient's balance of this
     * L2 token. This call will fail if it did not originate from a corresponding deposit in
     * L1StandardTokenBridge.
     * @param _l1Token Address for the l1 token this is called with
     * @param _l2Token Address for the l2 token this is called with
     * @param _from Account to pull the deposit from on L2.
     * @param _to Address to receive the withdrawal at
     * @param _amount Amount of the token to withdraw
     * @param _data Data provider by the sender on L1. This data is provided
     *        solely as a convenience for external contracts. Aside from enforcing a maximum
     *        length, these contracts provide no guarantees about its content.
     */
    function finalizeDeposit(
        address _l1Token,
        address _l2Token,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    ) external;
}

File 6 of 14 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 7 of 14 : CrossDomainEnabled.sol
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;

/* Interface Imports */
import { ICrossDomainMessenger } from "./ICrossDomainMessenger.sol";

/**
 * @title CrossDomainEnabled
 * @dev Helper contract for contracts performing cross-domain communications
 *
 * Compiler used: defined by inheriting contract
 * Runtime target: defined by inheriting contract
 */
contract CrossDomainEnabled {
    /*************
     * Variables *
     *************/

    // Messenger contract used to send and recieve messages from the other domain.
    address public messenger;


    /***************
     * Constructor *
     ***************/

    /**
     * @param _messenger Address of the CrossDomainMessenger on the current layer.
     */
    constructor(address _messenger) {
        messenger = _messenger;
    }

    /**********************
     * Function Modifiers *
     **********************/

    /**
     * Enforces that the modified function is only callable by a specific cross-domain account.
     * @param _sourceDomainAccount The only account on the originating domain which is
     *  authenticated to call this function.
     */
    modifier onlyFromCrossDomainAccount(address _sourceDomainAccount) {
        require(
            msg.sender == address(getCrossDomainMessenger()),
            "OVM_XCHAIN: messenger contract unauthenticated"
        );

        require(
            getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount,
            "OVM_XCHAIN: wrong sender of cross-domain message"
        );

        _;
    }

    /**********************
     * Internal Functions *
     **********************/

    /**
     * Gets the messenger, usually from storage. This function is exposed in case a child contract
     * needs to override.
     * @return The address of the cross-domain messenger contract which should be used.
     */
    function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {
        return ICrossDomainMessenger(messenger);
    }

    /**q
     * Sends a message to an account on another domain
     * @param _crossDomainTarget The intended recipient on the destination domain
     * @param _message The data to send to the target (usually calldata to a function with
     *  `onlyFromCrossDomainAccount()`)
     * @param _gasLimit The gasLimit for the receipt of the message on the target domain.
     */
    function sendCrossDomainMessage(
        address _crossDomainTarget,
        uint32 _gasLimit,
        bytes memory _message,
        uint256 fee
    )
        internal
    {
        getCrossDomainMessenger().sendMessage{value:fee}(_crossDomainTarget, _message, _gasLimit);
    }

    /**
     * @notice Sends a message to an account on another domain
     * @param _chainId L2 chain id.
     * @param _crossDomainTarget The intended recipient on the destination domain
     * @param _gasLimit The gasLimit for the receipt of the message on the target domain.
     * @param _message The data to send to the target (usually calldata to a function with `onlyFromCrossDomainAccount()`)
     */
    function sendCrossDomainMessageViaChainId(
        uint256 _chainId,
        address _crossDomainTarget,
        uint32 _gasLimit,
        bytes memory _message,
        uint256 fee
    ) internal {
        getCrossDomainMessenger().sendMessageViaChainId{value:fee}(_chainId, _crossDomainTarget, _message, _gasLimit);
    }
}

File 8 of 14 : Lib_PredeployAddresses.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

/**
 * @title Lib_PredeployAddresses
 */
library Lib_PredeployAddresses {
    address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;
    address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;
    address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;
    address internal constant MVM_CHAIN_CONFIG = 0x4200000000000000000000000000000000000005;
    address internal constant OVM_ETH = 0x420000000000000000000000000000000000000A;
    address internal constant MVM_COINBASE = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;
    address internal constant L2_CROSS_DOMAIN_MESSENGER =
        0x4200000000000000000000000000000000000007;
    address internal constant LIB_ADDRESS_MANAGER = 0x4200000000000000000000000000000000000008;
    address internal constant PROXY_EOA = 0x4200000000000000000000000000000000000009;
    address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;
    address payable internal constant SEQUENCER_FEE_WALLET = payable(0x4200000000000000000000000000000000000011);
    address internal constant L2_STANDARD_TOKEN_FACTORY =
        0x4200000000000000000000000000000000000012;
    address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;
    address internal constant OVM_GASPRICE_ORACLE = 0x420000000000000000000000000000000000000F;
    
}

File 9 of 14 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 10 of 14 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 11 of 14 : iMVM_DiscountOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

interface iMVM_DiscountOracle{

    function setDiscount(
        uint256 _discount
    ) external;
    
    function setMinL2Gas(
        uint256 _minL2Gas
    ) external;
    
    function setWhitelistedXDomainSender(
        address _sender,
        bool _isWhitelisted
    ) external;
    
    function isXDomainSenderAllowed(
        address _sender
    ) view external returns(bool);
    
    function setAllowAllXDomainSenders(
        bool _allowAllXDomainSenders
    ) external;
    
    function getMinL2Gas() view external returns(uint256);
    function getDiscount() view external returns(uint256);
    function processL2SeqGas(address sender, uint256 _chainId) external payable;
}

File 12 of 14 : Lib_AddressManager.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

/* External Imports */
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title Lib_AddressManager
 */
contract Lib_AddressManager is Ownable {
    /**********
     * Events *
     **********/

    event AddressSet(string indexed _name, address _newAddress, address _oldAddress);

    /*************
     * Variables *
     *************/

    mapping(bytes32 => address) private addresses;

    /********************
     * Public Functions *
     ********************/

    /**
     * Changes the address associated with a particular name.
     * @param _name String name to associate an address with.
     * @param _address Address to associate with the name.
     */
    function setAddress(string memory _name, address _address) external onlyOwner {
        bytes32 nameHash = _getNameHash(_name);
        address oldAddress = addresses[nameHash];
        addresses[nameHash] = _address;

        emit AddressSet(_name, _address, oldAddress);
    }

    /**
     * Retrieves the address associated with a given name.
     * @param _name Name to retrieve an address for.
     * @return Address associated with the given name.
     */
    function getAddress(string memory _name) external view returns (address) {
        return addresses[_getNameHash(_name)];
    }

    /**********************
     * Internal Functions *
     **********************/

    /**
     * Computes the hash of a name.
     * @param _name Name to compute a hash for.
     * @return Hash of the given name.
     */
    function _getNameHash(string memory _name) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(_name));
    }
}

File 13 of 14 : ICrossDomainMessenger.sol
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;

/**
 * @title ICrossDomainMessenger
 */
interface ICrossDomainMessenger {
    /**********
     * Events *
     **********/

    event SentMessage(
        address indexed target,
        address sender,
        bytes message,
        uint256 messageNonce,
        uint256 gasLimit,
        uint256 chainId
    );
    event RelayedMessage(bytes32 indexed msgHash);
    event FailedRelayedMessage(bytes32 indexed msgHash);

    /*************
     * Variables *
     *************/

    function xDomainMessageSender() external view returns (address);

    /********************
     * Public Functions *
     ********************/
    
    /**
     * Sends a cross domain message to the target messenger.
     * @param _target Target contract address.
     * @param _message Message to send to the target.
     * @param _gasLimit Gas limit for the provided message.
     */
    function sendMessage(
        address _target,
        bytes calldata _message,
        uint32 _gasLimit
    ) external payable;


    /**
     * Sends a cross domain message to the target messenger.
     * @param _chainId L2 chain id.
     * @param _target Target contract address.
     * @param _message Message to send to the target.
     * @param _gasLimit Gas limit for the provided message.
     */
    function sendMessageViaChainId(
        uint256 _chainId,
        address _target,
        bytes calldata _message,
        uint32 _gasLimit
    ) external payable;

}

File 14 of 14 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _setOwner(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _setOwner(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 15 of 14 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_chainid","type":"uint256"}],"name":"ERC20ChainID","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_l1Token","type":"address"},{"indexed":true,"internalType":"address","name":"_l2Token","type":"address"},{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"}],"name":"ERC20DepositInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_l1Token","type":"address"},{"indexed":true,"internalType":"address","name":"_l2Token","type":"address"},{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"}],"name":"ERC20WithdrawalFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"ETHDepositInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"ETHWithdrawalFinalized","type":"event"},{"inputs":[],"name":"DEFAULT_CHAINID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"addressmgr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_l2Gas","type":"uint32"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"depositERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainid","type":"uint256"},{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_l2Gas","type":"uint32"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"depositERC20ByChainId","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_l2Gas","type":"uint32"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"depositERC20To","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainid","type":"uint256"},{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_l2Gas","type":"uint32"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"depositERC20ToByChainId","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_l2Gas","type":"uint32"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"depositETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint32","name":"_l2Gas","type":"uint32"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"depositETHByChainId","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint32","name":"_l2Gas","type":"uint32"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"depositETHTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint32","name":"_l2Gas","type":"uint32"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"depositETHToByChainId","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"donateETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"finalizeERC20Withdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainid","type":"uint256"},{"internalType":"address","name":"_l1Token","type":"address"},{"internalType":"address","name":"_l2Token","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"finalizeERC20WithdrawalByChainId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"finalizeETHWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainid","type":"uint256"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"finalizeETHWithdrawalByChainId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainid","type":"uint256"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"finalizeMetisWithdrawalByChainId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_l1messenger","type":"address"},{"internalType":"address","name":"_l2TokenBridge","type":"address"},{"internalType":"address","name":"_metis","type":"address"},{"internalType":"address","name":"_addressmgr","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"l2TokenBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messenger","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metis","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50600080546001600160a01b0319169055612d07806100306000396000f3fe60806040526004361061016a5760003560e01c80638b4c40b0116100cb578063a9f9e6751161007f578063ef808be211610059578063ef808be214610371578063f4a1381414610384578063f8c8765e146103c257600080fd5b8063a9f9e6751461031e578063b1a1a8821461033e578063e59745541461035157600080fd5b806391c49bf8116100b057806391c49bf8146102d85780639a2ac6d5146102f8578063a396a59c1461030b57600080fd5b80638b4c40b01461018f57806390a40a76146102b857600080fd5b806358a997f6116101225780636cebdc45116101075780636cebdc4514610265578063838b25201461028557806384e930f0146102a557600080fd5b806358a997f6146102215780635bbbb7ed1461024157600080fd5b8063153928f411610153578063153928f4146101b1578063200997b3146101ee5780633cb747bf1461020157600080fd5b80630546aaa91461016f5780631532ec3414610191575b600080fd5b34801561017b57600080fd5b5061018f61018a3660046122cf565b6103e2565b005b34801561019d57600080fd5b5061018f6101ac36600461234b565b6106d1565b3480156101bd57600080fd5b506003546101d1906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61018f6101fc3660046123d7565b6109bc565b34801561020d57600080fd5b506000546101d1906001600160a01b031681565b34801561022d57600080fd5b5061018f61023c36600461242b565b610a06565b34801561024d57600080fd5b5061025761044081565b6040519081526020016101e5565b34801561027157600080fd5b5061018f610280366004612490565b610a70565b34801561029157600080fd5b5061018f6102a0366004612531565b610c37565b61018f6102b33660046125c7565b610c53565b3480156102c457600080fd5b5061018f6102d33660046122cf565b610ceb565b3480156102e457600080fd5b506001546101d1906001600160a01b031681565b61018f610306366004612621565b610ec8565b61018f610319366004612650565b610f0a565b34801561032a57600080fd5b5061018f61033936600461267d565b610f6a565b61018f61034c3660046126f6565b611132565b34801561035d57600080fd5b506002546101d1906001600160a01b031681565b61018f61037f366004612749565b6111c8565b34801561039057600080fd5b5061025761039f3660046127c8565b600460209081526000938452604080852082529284528284209052825290205481565b3480156103ce57600080fd5b5061018f6103dd36600461280a565b6111d9565b6001546001600160a01b03166104006000546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461048b5760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e7469636174656400000000000000000000000000000000000060648201526084015b60405180910390fd5b806001600160a01b03166104a76000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156104df57600080fd5b505afa1580156104f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105179190612866565b6001600160a01b0316146105935760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610482565b604080516000808252602082019092526001600160a01b0387169086906040516105bd91906128de565b60006040518083038185875af1925050503d80600081146105fa576040519150601f19603f3d011682016040523d82523d6000602084013e6105ff565b606091505b50509050806106765760405162461bcd60e51b815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527f20455448207472616e73666572206661696c65640000000000000000000000006064820152608401610482565b856001600160a01b0316876001600160a01b03167f727233b1ab656a027266fdc255d394b9aa8a2db3b7ff0fd6150dc3a8686f30cb8787878d6040516106bf9493929190612925565b60405180910390a35050505050505050565b6001546001600160a01b03166106ef6000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146107755760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e746963617465640000000000000000000000000000000000006064820152608401610482565b806001600160a01b03166107916000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156107c957600080fd5b505afa1580156107dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108019190612866565b6001600160a01b03161461087d5760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610482565b604080516000808252602082019092526001600160a01b0387169086906040516108a791906128de565b60006040518083038185875af1925050503d80600081146108e4576040519150601f19603f3d011682016040523d82523d6000602084013e6108e9565b606091505b50509050806109605760405162461bcd60e51b815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527f20455448207472616e73666572206661696c65640000000000000000000000006064820152608401610482565b856001600160a01b0316876001600160a01b03167f727233b1ab656a027266fdc255d394b9aa8a2db3b7ff0fd6150dc3a8686f30cb8787876104406040516109ab9493929190612925565b60405180910390a350505050505050565b6109ff8533868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506112c092505050565b5050505050565b333b15610a555760405162461bcd60e51b815260206004820152600f60248201527f4163636f756e74206e6f7420454f4100000000000000000000000000000000006044820152606401610482565b610a686104408787333389898989611613565b505050505050565b6001546001600160a01b0316610a8e6000546001600160a01b031690565b6001600160a01b0316336001600160a01b031614610b145760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e746963617465640000000000000000000000000000000000006064820152608401610482565b806001600160a01b0316610b306000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b158015610b6857600080fd5b505afa158015610b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba09190612866565b6001600160a01b031614610c1c5760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610482565b610c2c8989898989898989611bf8565b505050505050505050565b610c4a6104408888338989898989611613565b50505050505050565b333b15610ca25760405162461bcd60e51b815260206004820152600f60248201527f4163636f756e74206e6f7420454f4100000000000000000000000000000000006044820152606401610482565b610ce58433338686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506112c092505050565b50505050565b6001546001600160a01b0316610d096000546001600160a01b031690565b6001600160a01b0316336001600160a01b031614610d8f5760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e746963617465640000000000000000000000000000000000006064820152608401610482565b806001600160a01b0316610dab6000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b158015610de357600080fd5b505afa158015610df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1b9190612866565b6001600160a01b031614610e975760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610482565b600254610c4a9088906001600160a01b031673deaddeaddeaddeaddeaddeaddeaddeaddead00008989898989611bf8565b610ce533858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d0892505050565b333b15610f595760405162461bcd60e51b815260206004820152600f60248201527f4163636f756e74206e6f7420454f4100000000000000000000000000000000006044820152606401610482565b610c4a878787333389898989611613565b6001546001600160a01b0316610f886000546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461100e5760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e746963617465640000000000000000000000000000000000006064820152608401610482565b806001600160a01b031661102a6000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561106257600080fd5b505afa158015611076573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109a9190612866565b6001600160a01b0316146111165760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610482565b61112861044089898989898989611bf8565b5050505050505050565b333b156111815760405162461bcd60e51b815260206004820152600f60248201527f4163636f756e74206e6f7420454f4100000000000000000000000000000000006044820152606401610482565b6111c333338585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d0892505050565b505050565b611128888888338989898989611613565b6000546001600160a01b0316156112585760405162461bcd60e51b815260206004820152602660248201527f436f6e74726163742068617320616c7265616479206265656e20696e6974696160448201527f6c697a65642e00000000000000000000000000000000000000000000000000006064820152608401610482565b600080546001600160a01b039586167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556001805494861694821694909417909355600280549285169284169290921790915560038054919093169116179055565b6003546040517fbf40fac100000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4d564d5f446973636f756e744f7261636c65000000000000000000000000000060448201526000916001600160a01b03169063bf40fac19060640160206040518083038186803b15801561134b57600080fd5b505afa15801561135f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113839190612866565b90506000816001600160a01b031663bf53926e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113c057600080fd5b505afa1580156113d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f89190612950565b90508063ffffffff168463ffffffff161015611412578093505b6000826001600160a01b031663d137874b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561144d57600080fd5b505afa158015611461573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114859190612950565b6114959063ffffffff8716612998565b9050348111156114a482611d17565b6040516020016114b491906129d5565b604051602081830303815290604052906114e15760405162461bcd60e51b81526004016104829190612a6c565b5060007f662a633a000000000000000000000000000000000000000000000000000000008173420000000000000000000000000000000000000a8a8a6115278734612a7f565b8a60405160240161153d96959493929190612a96565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526001549091506115b9908a906001600160a01b0316888486611e74565b866001600160a01b0316886001600160a01b03167f742461272f8da1cbe655542d3257acb1f1d5f4e6eaa79692ac5609b0f89cb64434888d60405161160093929190612ae4565b60405180910390a3505050505050505050565b6003546040517fbf40fac100000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4d564d5f446973636f756e744f7261636c65000000000000000000000000000060448201526000916001600160a01b03169063bf40fac19060640160206040518083038186803b15801561169e57600080fd5b505afa1580156116b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d69190612866565b9050806001600160a01b031663bf53926e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561171157600080fd5b505afa158015611725573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117499190612950565b63ffffffff168463ffffffff1610156117d057806001600160a01b031663bf53926e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561179557600080fd5b505afa1580156117a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117cd9190612950565b93505b34816001600160a01b031663d137874b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561180a57600080fd5b505afa15801561181e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118429190612950565b6118529063ffffffff8716612998565b11156118dd826001600160a01b031663d137874b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561189057600080fd5b505afa1580156118a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c89190612950565b6118d89063ffffffff8816612998565b611d17565b6040516020016118ed91906129d5565b6040516020818303038152906040529061191a5760405162461bcd60e51b81526004016104829190612a6c565b506119306001600160a01b038a16883088611efe565b6002546060906001600160a01b038b811691161415611a065760405173deaddeaddeaddeaddeaddeaddeaddeaddead000099507f662a633a00000000000000000000000000000000000000000000000000000000906119a0906000908c908c908c908c908b908b90602401612b0d565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050611aa7565b6040517f662a633a0000000000000000000000000000000000000000000000000000000090611a45908c908c908c908c908c908b908b90602401612b0d565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290505b600154611ac1908c906001600160a01b0316878434611e74565b6001600160a01b03808b1660009081526004602090815260408083208f84528252808320938d1683529290522054611afa908790612b5d565b600460008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008d815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020819055507fc333b5c3e71358b85edbb94334230ac00644c26af29851f9034a7105eb84b0778b604051611b8891815260200190565b60405180910390a1876001600160a01b0316896001600160a01b03168b6001600160a01b03167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d03968a8a8989604051611be39493929190612b75565b60405180910390a45050505050505050505050565b6001600160a01b0380881660009081526004602090815260408083208c84528252808320938a1683529290522054611c31908490612a7f565b6001600160a01b0380891660008181526004602090815260408083208e84528252808320948c1683529390529190912091909155611c70908585611faf565b6040518881527fc333b5c3e71358b85edbb94334230ac00644c26af29851f9034a7105eb84b0779060200160405180910390a1846001600160a01b0316866001600160a01b0316886001600160a01b03167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b387878787604051611cf69493929190612b75565b60405180910390a45050505050505050565b610ce5610440858585856112c0565b606081611d5757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611d815780611d6b81612ba8565b9150611d7a9050600a83612be1565b9150611d5b565b60008167ffffffffffffffff811115611d9c57611d9c612883565b6040519080825280601f01601f191660200182016040528015611dc6576020820181803683370190505b509050815b8515611e6b57611ddc600182612a7f565b90506000611deb600a88612be1565b611df690600a612998565b611e009088612a7f565b611e0b906030612c1c565b905060008160f81b905080848481518110611e2857611e28612c41565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611e62600a89612be1565b97505050611dcb565b50949350505050565b6000546040517f44dd5ed60000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906344dd5ed6908390611ec5908990899088908a90600401612c70565b6000604051808303818588803b158015611ede57600080fd5b505af1158015611ef2573d6000803e3d6000fd5b50505050505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052610ce59085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611ff8565b6040516001600160a01b0383166024820152604481018290526111c39084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611f4b565b600061204d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120dd9092919063ffffffff16565b8051909150156111c3578080602001905181019061206b9190612caf565b6111c35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610482565b60606120ec84846000856120f6565b90505b9392505050565b60608247101561216e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610482565b843b6121bc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610482565b600080866001600160a01b031685876040516121d891906128de565b60006040518083038185875af1925050503d8060008114612215576040519150601f19603f3d011682016040523d82523d6000602084013e61221a565b606091505b509150915061222a828286612235565b979650505050505050565b606083156122445750816120ef565b8251156122545782518084602001fd5b8160405162461bcd60e51b81526004016104829190612a6c565b6001600160a01b038116811461228357600080fd5b50565b60008083601f84011261229857600080fd5b50813567ffffffffffffffff8111156122b057600080fd5b6020830191508360208285010111156122c857600080fd5b9250929050565b60008060008060008060a087890312156122e857600080fd5b8635955060208701356122fa8161226e565b9450604087013561230a8161226e565b935060608701359250608087013567ffffffffffffffff81111561232d57600080fd5b61233989828a01612286565b979a9699509497509295939492505050565b60008060008060006080868803121561236357600080fd5b853561236e8161226e565b9450602086013561237e8161226e565b935060408601359250606086013567ffffffffffffffff8111156123a157600080fd5b6123ad88828901612286565b969995985093965092949392505050565b803563ffffffff811681146123d257600080fd5b919050565b6000806000806000608086880312156123ef57600080fd5b8535945060208601356124018161226e565b935061240f604087016123be565b9250606086013567ffffffffffffffff8111156123a157600080fd5b60008060008060008060a0878903121561244457600080fd5b863561244f8161226e565b9550602087013561245f8161226e565b945060408701359350612474606088016123be565b9250608087013567ffffffffffffffff81111561232d57600080fd5b60008060008060008060008060e0898b0312156124ac57600080fd5b8835975060208901356124be8161226e565b965060408901356124ce8161226e565b955060608901356124de8161226e565b945060808901356124ee8161226e565b935060a0890135925060c089013567ffffffffffffffff81111561251157600080fd5b61251d8b828c01612286565b999c989b5096995094979396929594505050565b600080600080600080600060c0888a03121561254c57600080fd5b87356125578161226e565b965060208801356125678161226e565b955060408801356125778161226e565b94506060880135935061258c608089016123be565b925060a088013567ffffffffffffffff8111156125a857600080fd5b6125b48a828b01612286565b989b979a50959850939692959293505050565b600080600080606085870312156125dd57600080fd5b843593506125ed602086016123be565b9250604085013567ffffffffffffffff81111561260957600080fd5b61261587828801612286565b95989497509550505050565b6000806000806060858703121561263757600080fd5b84356126428161226e565b93506125ed602086016123be565b600080600080600080600060c0888a03121561266b57600080fd5b8735965060208801356125678161226e565b600080600080600080600060c0888a03121561269857600080fd5b87356126a38161226e565b965060208801356126b38161226e565b955060408801356126c38161226e565b945060608801356126d38161226e565b93506080880135925060a088013567ffffffffffffffff8111156125a857600080fd5b60008060006040848603121561270b57600080fd5b612714846123be565b9250602084013567ffffffffffffffff81111561273057600080fd5b61273c86828701612286565b9497909650939450505050565b60008060008060008060008060e0898b03121561276557600080fd5b8835975060208901356127778161226e565b965060408901356127878161226e565b955060608901356127978161226e565b9450608089013593506127ac60a08a016123be565b925060c089013567ffffffffffffffff81111561251157600080fd5b6000806000606084860312156127dd57600080fd5b83356127e88161226e565b92506020840135915060408401356127ff8161226e565b809150509250925092565b6000806000806080858703121561282057600080fd5b843561282b8161226e565b9350602085013561283b8161226e565b9250604085013561284b8161226e565b9150606085013561285b8161226e565b939692955090935050565b60006020828403121561287857600080fd5b81516120ef8161226e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b838110156128cd5781810151838201526020016128b5565b83811115610ce55750506000910152565b600082516128f08184602087016128b2565b9190910192915050565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b84815260606020820152600061293f6060830185876128fa565b905082604083015295945050505050565b60006020828403121561296257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156129d0576129d0612969565b500290565b7f696e73756666696369656e742066656520737570706c6965642e2073656e642081527f6174206c65617374200000000000000000000000000000000000000000000000602082015260008251612a338160298501602087016128b2565b9190910160290192915050565b60008151808452612a588160208601602086016128b2565b601f01601f19169290920160200192915050565b6020815260006120ef6020830184612a40565b600082821015612a9157612a91612969565b500390565b60006001600160a01b0380891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612ad860c0830184612a40565b98975050505050505050565b838152606060208201526000612afd6060830185612a40565b9050826040830152949350505050565b60006001600160a01b03808a1683528089166020840152808816604084015280871660608401525084608083015260c060a0830152612b5060c0830184866128fa565b9998505050505050505050565b60008219821115612b7057612b70612969565b500190565b6001600160a01b0385168152836020820152606060408201526000612b9e6060830184866128fa565b9695505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612bda57612bda612969565b5060010190565b600082612c17577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060ff821660ff84168060ff03821115612c3957612c39612969565b019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8481526001600160a01b0384166020820152608060408201526000612c986080830185612a40565b905063ffffffff8316606083015295945050505050565b600060208284031215612cc157600080fd5b815180151581146120ef57600080fdfea26469706673582212208f81963409ccb3b3d39ed6098aa70b0ef79c576dfec2be3c84aed20777ee1b4f64736f6c63430008090033

Deployed Bytecode

0x60806040526004361061016a5760003560e01c80638b4c40b0116100cb578063a9f9e6751161007f578063ef808be211610059578063ef808be214610371578063f4a1381414610384578063f8c8765e146103c257600080fd5b8063a9f9e6751461031e578063b1a1a8821461033e578063e59745541461035157600080fd5b806391c49bf8116100b057806391c49bf8146102d85780639a2ac6d5146102f8578063a396a59c1461030b57600080fd5b80638b4c40b01461018f57806390a40a76146102b857600080fd5b806358a997f6116101225780636cebdc45116101075780636cebdc4514610265578063838b25201461028557806384e930f0146102a557600080fd5b806358a997f6146102215780635bbbb7ed1461024157600080fd5b8063153928f411610153578063153928f4146101b1578063200997b3146101ee5780633cb747bf1461020157600080fd5b80630546aaa91461016f5780631532ec3414610191575b600080fd5b34801561017b57600080fd5b5061018f61018a3660046122cf565b6103e2565b005b34801561019d57600080fd5b5061018f6101ac36600461234b565b6106d1565b3480156101bd57600080fd5b506003546101d1906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61018f6101fc3660046123d7565b6109bc565b34801561020d57600080fd5b506000546101d1906001600160a01b031681565b34801561022d57600080fd5b5061018f61023c36600461242b565b610a06565b34801561024d57600080fd5b5061025761044081565b6040519081526020016101e5565b34801561027157600080fd5b5061018f610280366004612490565b610a70565b34801561029157600080fd5b5061018f6102a0366004612531565b610c37565b61018f6102b33660046125c7565b610c53565b3480156102c457600080fd5b5061018f6102d33660046122cf565b610ceb565b3480156102e457600080fd5b506001546101d1906001600160a01b031681565b61018f610306366004612621565b610ec8565b61018f610319366004612650565b610f0a565b34801561032a57600080fd5b5061018f61033936600461267d565b610f6a565b61018f61034c3660046126f6565b611132565b34801561035d57600080fd5b506002546101d1906001600160a01b031681565b61018f61037f366004612749565b6111c8565b34801561039057600080fd5b5061025761039f3660046127c8565b600460209081526000938452604080852082529284528284209052825290205481565b3480156103ce57600080fd5b5061018f6103dd36600461280a565b6111d9565b6001546001600160a01b03166104006000546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461048b5760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e7469636174656400000000000000000000000000000000000060648201526084015b60405180910390fd5b806001600160a01b03166104a76000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156104df57600080fd5b505afa1580156104f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105179190612866565b6001600160a01b0316146105935760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610482565b604080516000808252602082019092526001600160a01b0387169086906040516105bd91906128de565b60006040518083038185875af1925050503d80600081146105fa576040519150601f19603f3d011682016040523d82523d6000602084013e6105ff565b606091505b50509050806106765760405162461bcd60e51b815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527f20455448207472616e73666572206661696c65640000000000000000000000006064820152608401610482565b856001600160a01b0316876001600160a01b03167f727233b1ab656a027266fdc255d394b9aa8a2db3b7ff0fd6150dc3a8686f30cb8787878d6040516106bf9493929190612925565b60405180910390a35050505050505050565b6001546001600160a01b03166106ef6000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146107755760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e746963617465640000000000000000000000000000000000006064820152608401610482565b806001600160a01b03166107916000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156107c957600080fd5b505afa1580156107dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108019190612866565b6001600160a01b03161461087d5760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610482565b604080516000808252602082019092526001600160a01b0387169086906040516108a791906128de565b60006040518083038185875af1925050503d80600081146108e4576040519150601f19603f3d011682016040523d82523d6000602084013e6108e9565b606091505b50509050806109605760405162461bcd60e51b815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527f20455448207472616e73666572206661696c65640000000000000000000000006064820152608401610482565b856001600160a01b0316876001600160a01b03167f727233b1ab656a027266fdc255d394b9aa8a2db3b7ff0fd6150dc3a8686f30cb8787876104406040516109ab9493929190612925565b60405180910390a350505050505050565b6109ff8533868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506112c092505050565b5050505050565b333b15610a555760405162461bcd60e51b815260206004820152600f60248201527f4163636f756e74206e6f7420454f4100000000000000000000000000000000006044820152606401610482565b610a686104408787333389898989611613565b505050505050565b6001546001600160a01b0316610a8e6000546001600160a01b031690565b6001600160a01b0316336001600160a01b031614610b145760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e746963617465640000000000000000000000000000000000006064820152608401610482565b806001600160a01b0316610b306000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b158015610b6857600080fd5b505afa158015610b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba09190612866565b6001600160a01b031614610c1c5760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610482565b610c2c8989898989898989611bf8565b505050505050505050565b610c4a6104408888338989898989611613565b50505050505050565b333b15610ca25760405162461bcd60e51b815260206004820152600f60248201527f4163636f756e74206e6f7420454f4100000000000000000000000000000000006044820152606401610482565b610ce58433338686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506112c092505050565b50505050565b6001546001600160a01b0316610d096000546001600160a01b031690565b6001600160a01b0316336001600160a01b031614610d8f5760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e746963617465640000000000000000000000000000000000006064820152608401610482565b806001600160a01b0316610dab6000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b158015610de357600080fd5b505afa158015610df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1b9190612866565b6001600160a01b031614610e975760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610482565b600254610c4a9088906001600160a01b031673deaddeaddeaddeaddeaddeaddeaddeaddead00008989898989611bf8565b610ce533858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d0892505050565b333b15610f595760405162461bcd60e51b815260206004820152600f60248201527f4163636f756e74206e6f7420454f4100000000000000000000000000000000006044820152606401610482565b610c4a878787333389898989611613565b6001546001600160a01b0316610f886000546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461100e5760405162461bcd60e51b815260206004820152602e60248201527f4f564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e746963617465640000000000000000000000000000000000006064820152608401610482565b806001600160a01b031661102a6000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561106257600080fd5b505afa158015611076573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109a9190612866565b6001600160a01b0316146111165760405162461bcd60e51b815260206004820152603060248201527f4f564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610482565b61112861044089898989898989611bf8565b5050505050505050565b333b156111815760405162461bcd60e51b815260206004820152600f60248201527f4163636f756e74206e6f7420454f4100000000000000000000000000000000006044820152606401610482565b6111c333338585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d0892505050565b505050565b611128888888338989898989611613565b6000546001600160a01b0316156112585760405162461bcd60e51b815260206004820152602660248201527f436f6e74726163742068617320616c7265616479206265656e20696e6974696160448201527f6c697a65642e00000000000000000000000000000000000000000000000000006064820152608401610482565b600080546001600160a01b039586167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556001805494861694821694909417909355600280549285169284169290921790915560038054919093169116179055565b6003546040517fbf40fac100000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4d564d5f446973636f756e744f7261636c65000000000000000000000000000060448201526000916001600160a01b03169063bf40fac19060640160206040518083038186803b15801561134b57600080fd5b505afa15801561135f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113839190612866565b90506000816001600160a01b031663bf53926e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113c057600080fd5b505afa1580156113d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f89190612950565b90508063ffffffff168463ffffffff161015611412578093505b6000826001600160a01b031663d137874b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561144d57600080fd5b505afa158015611461573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114859190612950565b6114959063ffffffff8716612998565b9050348111156114a482611d17565b6040516020016114b491906129d5565b604051602081830303815290604052906114e15760405162461bcd60e51b81526004016104829190612a6c565b5060007f662a633a000000000000000000000000000000000000000000000000000000008173420000000000000000000000000000000000000a8a8a6115278734612a7f565b8a60405160240161153d96959493929190612a96565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526001549091506115b9908a906001600160a01b0316888486611e74565b866001600160a01b0316886001600160a01b03167f742461272f8da1cbe655542d3257acb1f1d5f4e6eaa79692ac5609b0f89cb64434888d60405161160093929190612ae4565b60405180910390a3505050505050505050565b6003546040517fbf40fac100000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4d564d5f446973636f756e744f7261636c65000000000000000000000000000060448201526000916001600160a01b03169063bf40fac19060640160206040518083038186803b15801561169e57600080fd5b505afa1580156116b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d69190612866565b9050806001600160a01b031663bf53926e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561171157600080fd5b505afa158015611725573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117499190612950565b63ffffffff168463ffffffff1610156117d057806001600160a01b031663bf53926e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561179557600080fd5b505afa1580156117a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117cd9190612950565b93505b34816001600160a01b031663d137874b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561180a57600080fd5b505afa15801561181e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118429190612950565b6118529063ffffffff8716612998565b11156118dd826001600160a01b031663d137874b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561189057600080fd5b505afa1580156118a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c89190612950565b6118d89063ffffffff8816612998565b611d17565b6040516020016118ed91906129d5565b6040516020818303038152906040529061191a5760405162461bcd60e51b81526004016104829190612a6c565b506119306001600160a01b038a16883088611efe565b6002546060906001600160a01b038b811691161415611a065760405173deaddeaddeaddeaddeaddeaddeaddeaddead000099507f662a633a00000000000000000000000000000000000000000000000000000000906119a0906000908c908c908c908c908b908b90602401612b0d565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050611aa7565b6040517f662a633a0000000000000000000000000000000000000000000000000000000090611a45908c908c908c908c908c908b908b90602401612b0d565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290505b600154611ac1908c906001600160a01b0316878434611e74565b6001600160a01b03808b1660009081526004602090815260408083208f84528252808320938d1683529290522054611afa908790612b5d565b600460008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008d815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020819055507fc333b5c3e71358b85edbb94334230ac00644c26af29851f9034a7105eb84b0778b604051611b8891815260200190565b60405180910390a1876001600160a01b0316896001600160a01b03168b6001600160a01b03167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d03968a8a8989604051611be39493929190612b75565b60405180910390a45050505050505050505050565b6001600160a01b0380881660009081526004602090815260408083208c84528252808320938a1683529290522054611c31908490612a7f565b6001600160a01b0380891660008181526004602090815260408083208e84528252808320948c1683529390529190912091909155611c70908585611faf565b6040518881527fc333b5c3e71358b85edbb94334230ac00644c26af29851f9034a7105eb84b0779060200160405180910390a1846001600160a01b0316866001600160a01b0316886001600160a01b03167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b387878787604051611cf69493929190612b75565b60405180910390a45050505050505050565b610ce5610440858585856112c0565b606081611d5757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611d815780611d6b81612ba8565b9150611d7a9050600a83612be1565b9150611d5b565b60008167ffffffffffffffff811115611d9c57611d9c612883565b6040519080825280601f01601f191660200182016040528015611dc6576020820181803683370190505b509050815b8515611e6b57611ddc600182612a7f565b90506000611deb600a88612be1565b611df690600a612998565b611e009088612a7f565b611e0b906030612c1c565b905060008160f81b905080848481518110611e2857611e28612c41565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611e62600a89612be1565b97505050611dcb565b50949350505050565b6000546040517f44dd5ed60000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906344dd5ed6908390611ec5908990899088908a90600401612c70565b6000604051808303818588803b158015611ede57600080fd5b505af1158015611ef2573d6000803e3d6000fd5b50505050505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052610ce59085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611ff8565b6040516001600160a01b0383166024820152604481018290526111c39084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611f4b565b600061204d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120dd9092919063ffffffff16565b8051909150156111c3578080602001905181019061206b9190612caf565b6111c35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610482565b60606120ec84846000856120f6565b90505b9392505050565b60608247101561216e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610482565b843b6121bc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610482565b600080866001600160a01b031685876040516121d891906128de565b60006040518083038185875af1925050503d8060008114612215576040519150601f19603f3d011682016040523d82523d6000602084013e61221a565b606091505b509150915061222a828286612235565b979650505050505050565b606083156122445750816120ef565b8251156122545782518084602001fd5b8160405162461bcd60e51b81526004016104829190612a6c565b6001600160a01b038116811461228357600080fd5b50565b60008083601f84011261229857600080fd5b50813567ffffffffffffffff8111156122b057600080fd5b6020830191508360208285010111156122c857600080fd5b9250929050565b60008060008060008060a087890312156122e857600080fd5b8635955060208701356122fa8161226e565b9450604087013561230a8161226e565b935060608701359250608087013567ffffffffffffffff81111561232d57600080fd5b61233989828a01612286565b979a9699509497509295939492505050565b60008060008060006080868803121561236357600080fd5b853561236e8161226e565b9450602086013561237e8161226e565b935060408601359250606086013567ffffffffffffffff8111156123a157600080fd5b6123ad88828901612286565b969995985093965092949392505050565b803563ffffffff811681146123d257600080fd5b919050565b6000806000806000608086880312156123ef57600080fd5b8535945060208601356124018161226e565b935061240f604087016123be565b9250606086013567ffffffffffffffff8111156123a157600080fd5b60008060008060008060a0878903121561244457600080fd5b863561244f8161226e565b9550602087013561245f8161226e565b945060408701359350612474606088016123be565b9250608087013567ffffffffffffffff81111561232d57600080fd5b60008060008060008060008060e0898b0312156124ac57600080fd5b8835975060208901356124be8161226e565b965060408901356124ce8161226e565b955060608901356124de8161226e565b945060808901356124ee8161226e565b935060a0890135925060c089013567ffffffffffffffff81111561251157600080fd5b61251d8b828c01612286565b999c989b5096995094979396929594505050565b600080600080600080600060c0888a03121561254c57600080fd5b87356125578161226e565b965060208801356125678161226e565b955060408801356125778161226e565b94506060880135935061258c608089016123be565b925060a088013567ffffffffffffffff8111156125a857600080fd5b6125b48a828b01612286565b989b979a50959850939692959293505050565b600080600080606085870312156125dd57600080fd5b843593506125ed602086016123be565b9250604085013567ffffffffffffffff81111561260957600080fd5b61261587828801612286565b95989497509550505050565b6000806000806060858703121561263757600080fd5b84356126428161226e565b93506125ed602086016123be565b600080600080600080600060c0888a03121561266b57600080fd5b8735965060208801356125678161226e565b600080600080600080600060c0888a03121561269857600080fd5b87356126a38161226e565b965060208801356126b38161226e565b955060408801356126c38161226e565b945060608801356126d38161226e565b93506080880135925060a088013567ffffffffffffffff8111156125a857600080fd5b60008060006040848603121561270b57600080fd5b612714846123be565b9250602084013567ffffffffffffffff81111561273057600080fd5b61273c86828701612286565b9497909650939450505050565b60008060008060008060008060e0898b03121561276557600080fd5b8835975060208901356127778161226e565b965060408901356127878161226e565b955060608901356127978161226e565b9450608089013593506127ac60a08a016123be565b925060c089013567ffffffffffffffff81111561251157600080fd5b6000806000606084860312156127dd57600080fd5b83356127e88161226e565b92506020840135915060408401356127ff8161226e565b809150509250925092565b6000806000806080858703121561282057600080fd5b843561282b8161226e565b9350602085013561283b8161226e565b9250604085013561284b8161226e565b9150606085013561285b8161226e565b939692955090935050565b60006020828403121561287857600080fd5b81516120ef8161226e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b838110156128cd5781810151838201526020016128b5565b83811115610ce55750506000910152565b600082516128f08184602087016128b2565b9190910192915050565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b84815260606020820152600061293f6060830185876128fa565b905082604083015295945050505050565b60006020828403121561296257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156129d0576129d0612969565b500290565b7f696e73756666696369656e742066656520737570706c6965642e2073656e642081527f6174206c65617374200000000000000000000000000000000000000000000000602082015260008251612a338160298501602087016128b2565b9190910160290192915050565b60008151808452612a588160208601602086016128b2565b601f01601f19169290920160200192915050565b6020815260006120ef6020830184612a40565b600082821015612a9157612a91612969565b500390565b60006001600160a01b0380891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612ad860c0830184612a40565b98975050505050505050565b838152606060208201526000612afd6060830185612a40565b9050826040830152949350505050565b60006001600160a01b03808a1683528089166020840152808816604084015280871660608401525084608083015260c060a0830152612b5060c0830184866128fa565b9998505050505050505050565b60008219821115612b7057612b70612969565b500190565b6001600160a01b0385168152836020820152606060408201526000612b9e6060830184866128fa565b9695505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612bda57612bda612969565b5060010190565b600082612c17577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060ff821660ff84168060ff03821115612c3957612c39612969565b019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8481526001600160a01b0384166020820152608060408201526000612c986080830185612a40565b905063ffffffff8316606083015295945050505050565b600060208284031215612cc157600080fd5b815180151581146120ef57600080fdfea26469706673582212208f81963409ccb3b3d39ed6098aa70b0ef79c576dfec2be3c84aed20777ee1b4f64736f6c63430008090033

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
[ 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.