ETH Price: $3,319.77 (-3.47%)
Gas: 9.17 Gwei

Contract

0xc37F520455dfA31E3a304434c7d44d282baeBcDB
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0x60806040126408522021-06-15 19:06:281260 days ago1623783988IN
 Create: L1GatewayRouter
0 ETH0.0454018232.00000145

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
L1GatewayRouter

Compiler Version
v0.6.11+commit.5ef660b1

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion
File 1 of 14 : L1GatewayRouter.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "arb-bridge-eth/contracts/libraries/Whitelist.sol";

import { L1ArbitrumMessenger } from "../../libraries/gateway/ArbitrumMessenger.sol";
import "../../libraries/gateway/GatewayRouter.sol";
import "../../arbitrum/gateway/L2GatewayRouter.sol";

/**
 * @title Handles deposits from Erhereum into Arbitrum. Tokens are routered to their appropriate L1 gateway (Router itself also conforms to the Gateway itnerface).
 * @notice Router also serves as an L1-L2 token address oracle.
 */
contract L1GatewayRouter is WhitelistConsumer, L1ArbitrumMessenger, GatewayRouter {
    address public owner;
    address public inbox;

    modifier onlyOwner {
        require(msg.sender == owner, "ONLY_OWNER");
        _;
    }

    function initialize(
        address _owner,
        address _defaultGateway,
        address _whitelist,
        address _counterpartGateway,
        address _inbox
    ) public virtual {
        GatewayRouter._initialize(_counterpartGateway, _defaultGateway);
        owner = _owner;
        WhitelistConsumer.whitelist = _whitelist;
        inbox = _inbox;
    }

    function sendTxToL2(
        address _user,
        uint256 _l2CallValue,
        uint256 _maxSubmissionCost,
        uint256 _maxGas,
        uint256 _gasPriceBid,
        bytes memory _data
    ) internal virtual returns (uint256) {
        return
            L1ArbitrumMessenger.sendTxToL2(
                inbox,
                counterpartGateway,
                _user,
                _l2CallValue,
                _maxSubmissionCost,
                _maxGas,
                _gasPriceBid,
                _data
            );
    }

    function setDefaultGateway(
        address newL1DefaultGateway,
        uint256 _maxGas,
        uint256 _gasPriceBid,
        uint256 _maxSubmissionCost
    ) external payable virtual onlyOwner returns (uint256) {
        defaultGateway = newL1DefaultGateway;

        emit DefaultGatewayUpdated(newL1DefaultGateway);

        address l2NewDefaultGateway;

        if (newL1DefaultGateway != address(0)) {
            l2NewDefaultGateway = TokenGateway(newL1DefaultGateway).counterpartGateway();
        }

        bytes memory data =
            abi.encodeWithSelector(L2GatewayRouter.setDefaultGateway.selector, l2NewDefaultGateway);

        return sendTxToL2(msg.sender, 0, _maxSubmissionCost, _maxGas, _gasPriceBid, data);
    }

    function setOwner(address newOwner) external onlyOwner {
        require(newOwner != address(0), "INVALID_OWNER");
        // set newOwner to address(1) to disable owner and keep `initialize` safe
        owner = newOwner;
    }

    function _setGateways(
        address[] memory _token,
        address[] memory _gateway,
        uint256 _maxGas,
        uint256 _gasPriceBid,
        uint256 _maxSubmissionCost
    ) internal returns (uint256) {
        require(_token.length == _gateway.length, "WRONG_LENGTH");

        for (uint256 i = 0; i < _token.length; i++) {
            l1TokenToGateway[_token[i]] = _gateway[i];
            emit GatewaySet(_token[i], _gateway[i]);
            // overwrite memory so the L2 router receives the L2 address of each gateway
            if (_gateway[i] != address(0)) {
                _gateway[i] = TokenGateway(_gateway[i]).counterpartGateway();
            }
        }

        bytes memory data =
            abi.encodeWithSelector(L2GatewayRouter.setGateway.selector, _token, _gateway);

        return sendTxToL2(msg.sender, 0, _maxSubmissionCost, _maxGas, _gasPriceBid, data);
    }

    function setGateway(
        address _gateway,
        uint256 _maxGas,
        uint256 _gasPriceBid,
        uint256 _maxSubmissionCost
    ) external payable returns (uint256) {
        require(address(msg.sender).isContract(), "NOT_FROM_CONTRACT");
        require(_gateway.isContract(), "NOT_TO_CONTRACT");

        address[] memory _tokenArr = new address[](1);
        _tokenArr[0] = address(msg.sender);

        address[] memory _gatewayArr = new address[](1);
        _gatewayArr[0] = _gateway;

        return _setGateways(_tokenArr, _gatewayArr, _maxGas, _gasPriceBid, _maxSubmissionCost);
    }

    function setGateways(
        address[] memory _token,
        address[] memory _gateway,
        uint256 _maxGas,
        uint256 _gasPriceBid,
        uint256 _maxSubmissionCost
    ) external payable onlyOwner returns (uint256) {
        // it is assumed that token and gateway are both contracts
        // require(_token[i].isContract() && _gateway[i].isContract(), "NOT_CONTRACT");
        return _setGateways(_token, _gateway, _maxGas, _gasPriceBid, _maxSubmissionCost);
    }

    function outboundTransfer(
        address _token,
        address _to,
        uint256 _amount,
        uint256 _maxGas,
        uint256 _gasPriceBid,
        bytes calldata _data
    ) public payable virtual override onlyWhitelisted returns (bytes memory) {
        // will revert if msg.sender is not whitelisted
        super.outboundTransfer(_token, _to, _amount, _maxGas, _gasPriceBid, _data);
    }

    function isCounterpartGateway(address _target) internal view virtual override returns (bool) {
        // don't expect messages from L2 router
        return false;
    }
}

File 2 of 14 : Whitelist.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2021, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

abstract contract WhitelistConsumer {
    address public whitelist;

    event WhitelistSourceUpdated(address newSource);

    modifier onlyWhitelisted {
        if (whitelist != address(0)) {
            require(Whitelist(whitelist).isAllowed(msg.sender), "NOT_WHITELISTED");
        }
        _;
    }

    function updateWhitelistSource(address newSource) external {
        require(msg.sender == whitelist, "NOT_FROM_LIST");
        whitelist = newSource;
        emit WhitelistSourceUpdated(newSource);
    }
}

contract Whitelist {
    address public owner;
    mapping(address => bool) public isAllowed;

    event OwnerUpdated(address newOwner);
    event WhitelistUpgraded(address newWhitelist, address[] targets);

    constructor() public {
        owner = msg.sender;
    }

    modifier onlyOwner {
        require(msg.sender == owner, "ONLY_OWNER");
        _;
    }

    function setOwner(address newOwner) external onlyOwner {
        owner = newOwner;
        emit OwnerUpdated(newOwner);
    }

    function setWhitelist(address[] memory user, bool[] memory val) external onlyOwner {
        require(user.length == val.length, "INVALID_INPUT");

        for (uint256 i = 0; i < user.length; i++) {
            isAllowed[user[i]] = val[i];
        }
    }

    // set new whitelist to address(0) to disable whitelist
    function triggerConsumers(address newWhitelist, address[] memory targets) external onlyOwner {
        for (uint256 i = 0; i < targets.length; i++) {
            WhitelistConsumer(targets[i]).updateWhitelistSource(newWhitelist);
        }
        emit WhitelistUpgraded(newWhitelist, targets);
    }
}

File 3 of 14 : ArbitrumMessenger.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "arb-bridge-eth/contracts/bridge/interfaces/IInbox.sol";
import "arb-bridge-eth/contracts/bridge/interfaces/IOutbox.sol";
import "arbos-contracts/arbos/builtin/ArbSys.sol";

abstract contract L1ArbitrumMessenger {
    event TxToL2(address indexed _from, address indexed _to, uint256 indexed _seqNum, bytes _data);

    function sendTxToL2(
        address _inbox,
        address _to,
        address _user,
        uint256 _l2CallValue,
        uint256 _maxSubmissionCost,
        uint256 _maxGas,
        uint256 _gasPriceBid,
        bytes memory _data
    ) internal virtual returns (uint256) {
        uint256 seqNum =
            IInbox(_inbox).createRetryableTicket{ value: msg.value }(
                _to,
                _l2CallValue,
                _maxSubmissionCost,
                _user,
                _user,
                _maxGas,
                _gasPriceBid,
                _data
            );
        emit TxToL2(_user, _to, seqNum, _data);
        return seqNum;
    }

    function getL2ToL1Sender(address _inbox) internal view virtual returns (address) {
        IOutbox outbox = IOutbox(IInbox(_inbox).bridge().activeOutbox());
        address l2ToL1Sender = outbox.l2ToL1Sender();

        require(l2ToL1Sender != address(0), "NO_SENDER");
        return l2ToL1Sender;
    }
}

abstract contract L2ArbitrumMessenger {
    address internal constant arbsysAddr = address(100);

    event TxToL1(address indexed _from, address indexed _to, uint256 indexed _id, bytes _data);

    function sendTxToL1(
        uint256 _l1CallValue,
        address _from,
        address _to,
        bytes memory _data
    ) internal virtual returns (uint256) {
        uint256 _id = ArbSys(arbsysAddr).sendTxToL1{ value: _l1CallValue }(_to, _data);
        emit TxToL1(_from, _to, _id, _data);
        return _id;
    }
}

File 4 of 14 : GatewayRouter.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "@openzeppelin/contracts/utils/Address.sol";
import "./TokenGateway.sol";
import "./IGatewayRouter.sol";

/**
 * @title Common interface for L1 and L2 Gateway Routers
 */
abstract contract GatewayRouter is TokenGateway, IGatewayRouter {
    using Address for address;

    address internal constant ZERO_ADDR = address(0);
    address internal constant BLACKLISTED = address(1);

    mapping(address => address) public l1TokenToGateway;
    address public defaultGateway;

    event TransferRouted(
        address indexed token,
        address indexed _userFrom,
        address indexed _userTo,
        address gateway
    );

    event GatewaySet(address indexed l1Token, address indexed gateway);
    event DefaultGatewayUpdated(address newDefaultGateway);

    function _initialize(address _counterpartGateway, address _defaultGateway)
        internal
        virtual
        override
    {
        TokenGateway._initialize(_counterpartGateway, address(0));
        defaultGateway = _defaultGateway;
    }

    function isRouter() external view override returns (bool) {
        return true;
    }

    function finalizeInboundTransfer(
        address _token,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    ) external payable virtual override(TokenGateway, ITokenGateway) returns (bytes memory) {
        revert("ONLY_OUTBOUND_ROUTER");
    }

    function outboundTransfer(
        address _token,
        address _to,
        uint256 _amount,
        uint256 _maxGas,
        uint256 _gasPriceBid,
        bytes calldata _data
    ) public payable virtual override(TokenGateway, ITokenGateway) returns (bytes memory) {
        address gateway = getGateway(_token);
        bytes memory gatewayData = getOutboundCalldata(_token, msg.sender, _to, _amount, _data);

        emit TransferRouted(_token, msg.sender, _to, gateway);
        return
            ITokenGateway(gateway).outboundTransfer{ value: msg.value }(
                _token,
                _to,
                _amount,
                _maxGas,
                _gasPriceBid,
                gatewayData
            );
    }

    function getOutboundCalldata(
        address _token,
        address _from,
        address _to,
        uint256 _amount,
        bytes memory _data
    ) public view virtual override returns (bytes memory) {
        return abi.encode(_from, _data);
    }

    function isRouter(address _target) internal view virtual override returns (bool) {
        // nothing routes to gateway router
        return false;
    }

    function getGateway(address _token) public view virtual returns (address gateway) {
        gateway = l1TokenToGateway[_token];
        require(gateway != BLACKLISTED, "BLACKLIST");

        if (gateway == ZERO_ADDR) {
            gateway = defaultGateway;
        }

        require(gateway.isContract(), "NO_GATEWAY_DEPLOYED");

        return gateway;
    }

    function _calculateL2TokenAddress(address l1ERC20)
        internal
        view
        virtual
        override
        returns (address)
    {
        return TokenGateway(getGateway(l1ERC20)).calculateL2TokenAddress(l1ERC20);
    }
}

File 5 of 14 : L2GatewayRouter.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "../../libraries/gateway/GatewayRouter.sol";
import "../../ethereum/gateway/L1GatewayRouter.sol";

/**
 * @title Handles withdrawals from Ethereum into Arbitrum. Tokens are routered to their appropriate L2 gateway (Router itself also conforms to the Gateway interface).
 * @notice Router also serves as an L2-L1 token address oracle.
 */
contract L2GatewayRouter is GatewayRouter {
    function initialize(address _counterpartGateway, address _defaultGateway) public virtual {
        GatewayRouter._initialize(_counterpartGateway, _defaultGateway);
    }

    function setGateway(address[] memory _l1Token, address[] memory _gateway)
        external
        virtual
        onlyCounterpartGateway
    {
        // counterpart gateway (L1 router) should never allow wrong lengths
        assert(_l1Token.length == _gateway.length);

        for (uint256 i = 0; i < _l1Token.length; i++) {
            l1TokenToGateway[_l1Token[i]] = _gateway[i];
            emit GatewaySet(_l1Token[i], _gateway[i]);
        }
    }

    function outboundTransfer(
        address _l1Token,
        address _to,
        uint256 _amount,
        bytes calldata _data
    ) public payable virtual returns (bytes memory) {
        return outboundTransfer(_l1Token, _to, _amount, 0, 0, _data);
    }

    function setDefaultGateway(address newL2DefaultGateway)
        external
        virtual
        onlyCounterpartGateway
    {
        defaultGateway = newL2DefaultGateway;
        emit DefaultGatewayUpdated(newL2DefaultGateway);
    }
}

File 6 of 14 : IInbox.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2021, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "./IBridge.sol";
import "./IMessageProvider.sol";

interface IInbox is IMessageProvider {
    function sendL2Message(bytes calldata messageData) external returns (uint256);

    function sendUnsignedTransaction(
        uint256 maxGas,
        uint256 gasPriceBid,
        uint256 nonce,
        address destAddr,
        uint256 amount,
        bytes calldata data
    ) external returns (uint256);

    function sendContractTransaction(
        uint256 maxGas,
        uint256 gasPriceBid,
        address destAddr,
        uint256 amount,
        bytes calldata data
    ) external returns (uint256);

    function sendL1FundedUnsignedTransaction(
        uint256 maxGas,
        uint256 gasPriceBid,
        uint256 nonce,
        address destAddr,
        bytes calldata data
    ) external payable returns (uint256);

    function sendL1FundedContractTransaction(
        uint256 maxGas,
        uint256 gasPriceBid,
        address destAddr,
        bytes calldata data
    ) external payable returns (uint256);

    function createRetryableTicket(
        address destAddr,
        uint256 arbTxCallValue,
        uint256 maxSubmissionCost,
        address submissionRefundAddress,
        address valueRefundAddress,
        uint256 maxGas,
        uint256 gasPriceBid,
        bytes calldata data
    ) external payable returns (uint256);

    function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);

    function bridge() external view returns (IBridge);
}

File 7 of 14 : IOutbox.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2021, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

interface IOutbox {
    event OutboxEntryCreated(
        uint256 indexed batchNum,
        uint256 outboxIndex,
        bytes32 outputRoot,
        uint256 numInBatch
    );
    event OutBoxTransactionExecuted(
        address indexed destAddr,
        address indexed l2Sender,
        uint256 indexed outboxIndex,
        uint256 transactionIndex
    );

    function l2ToL1Sender() external view returns (address);

    function l2ToL1Block() external view returns (uint256);

    function l2ToL1EthBlock() external view returns (uint256);

    function l2ToL1Timestamp() external view returns (uint256);

    function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths)
        external;
}

File 8 of 14 : ArbSys.sol
pragma solidity >=0.4.21 <0.7.0;

/**
* @title Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. Exposes a variety of system-level functionality.
 */
interface ArbSys {
    /**
    * @notice Get internal version number identifying an ArbOS build
    * @return version number as int
     */
    function arbOSVersion() external pure returns (uint);

    function arbChainID() external view returns(uint);

    /**
    * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)
    * @return block number as int
     */ 
    function arbBlockNumber() external view returns (uint);

    /** 
    * @notice Send given amount of Eth to dest from sender.
    * This is a convenience function, which is equivalent to calling sendTxToL1 with empty calldataForL1.
    * @param destination recipient address on L1
    * @return unique identifier for this L2-to-L1 transaction.
    */
    function withdrawEth(address destination) external payable returns(uint);

    /** 
    * @notice Send a transaction to L1
    * @param destination recipient address on L1 
    * @param calldataForL1 (optional) calldata for L1 contract call
    * @return a unique identifier for this L2-to-L1 transaction.
    */
    function sendTxToL1(address destination, bytes calldata calldataForL1) external payable returns(uint);

    /** 
    * @notice get the number of transactions issued by the given external account or the account sequence number of the given contract
    * @param account target account
    * @return the number of transactions issued by the given external account or the account sequence number of the given contract
    */
    function getTransactionCount(address account) external view returns(uint256);

    /**  
    * @notice get the value of target L2 storage slot 
    * This function is only callable from address 0 to prevent contracts from being able to call it
    * @param account target account
    * @param index target index of storage slot 
    * @return stotage value for the given account at the given index
    */
    function getStorageAt(address account, uint256 index) external view returns (uint256);

    /**
    * @notice check if current call is coming from l1
    * @return true if the caller of this was called directly from L1
    */
    function isTopLevelCall() external view returns (bool);

    event EthWithdrawal(address indexed destAddr, uint amount);

    event L2ToL1Transaction(address caller, address indexed destination, uint indexed uniqueId,
                            uint indexed batchNumber, uint indexInBatch,
                            uint arbBlockNum, uint ethBlockNum, uint timestamp,
                            uint callvalue, bytes data);
}

File 9 of 14 : IBridge.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2021, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

interface IBridge {
    event MessageDelivered(
        uint256 indexed messageIndex,
        bytes32 indexed beforeInboxAcc,
        address inbox,
        uint8 kind,
        address sender,
        bytes32 messageDataHash
    );

    function deliverMessageToInbox(
        uint8 kind,
        address sender,
        bytes32 messageDataHash
    ) external payable returns (uint256);

    function executeCall(
        address destAddr,
        uint256 amount,
        bytes calldata data
    ) external returns (bool success, bytes memory returnData);

    // These are only callable by the admin
    function setInbox(address inbox, bool enabled) external;

    function setOutbox(address inbox, bool enabled) external;

    // View functions

    function activeOutbox() external view returns (address);

    function allowedInboxes(address inbox) external view returns (bool);

    function allowedOutboxes(address outbox) external view returns (bool);

    function inboxAccs(uint256 index) external view returns (bytes32);

    function messageCount() external view returns (uint256);
}

File 10 of 14 : IMessageProvider.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2021, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

interface IMessageProvider {
    event InboxMessageDelivered(uint256 indexed messageNum, bytes data);

    event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);
}

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

pragma solidity >=0.6.2 <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;
        // solhint-disable-next-line no-inline-assembly
        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");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 12 of 14 : TokenGateway.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "./ITokenGateway.sol";
import "./IGatewayRouter.sol";
import "@openzeppelin/contracts/utils/Address.sol";

abstract contract TokenGateway is ITokenGateway {
    using Address for address;
    address public counterpartGateway;
    address public STORAGE_GAP;

    modifier onlyCounterpartGateway {
        require(isCounterpartGateway(msg.sender), "ONLY_COUNTERPART_GATEWAY");
        _;
    }

    function _initialize(address _counterpartGateway, address _router) internal virtual {
        require(_counterpartGateway != address(0), "INVALID_COUNTERPART");
        require(counterpartGateway == address(0), "ALREADY_INIT");
        counterpartGateway = _counterpartGateway;
        // TODO: remove _router parameter
    }

    /**
     * @notice Calculate the address used when bridging an ERC20 token
     * @dev this always returns the same as the L1 oracle, but may be out of date.
     * For example, a custom token may have been registered but not deploy or the contract self destructed.
     * @param l1ERC20 address of L1 token
     * @return L2 address of a bridged ERC20 token
     */
    function calculateL2TokenAddress(address l1ERC20)
        external
        view
        virtual
        override
        returns (address)
    {
        // will revert if not called by router
        return _calculateL2TokenAddress(l1ERC20);
    }

    /**
     * @notice Calculate the address used when bridging an ERC20 token
     * @dev this always returns the same as the L1 oracle, but may be out of date.
     * For example, a custom token may have been registered but not deploy or the contract self destructed.
     * @param l1ERC20 address of L1 token
     * @return L2 address of a bridged ERC20 token
     */
    function _calculateL2TokenAddress(address l1ERC20) internal view virtual returns (address);

    bytes internal constant BYTES_ONE = abi.encode(true);

    function isRouter(address _target) internal view virtual returns (bool isTargetRouter) {
        (bool success, bytes memory ret) =
            _target.staticcall(abi.encodeWithSelector(IGatewayRouter.isRouter.selector));

        if (!_target.isContract()) return false;
        if (!success) return false;

        // if calling an EOA the default value of this will be 0
        assembly {
            isTargetRouter := mload(ret)
        }

        return isTargetRouter;
    }

    function isCounterpartGateway(address _target) internal view virtual returns (bool) {
        return _target == counterpartGateway;
    }

    function outboundTransfer(
        address _token,
        address _to,
        uint256 _amount,
        uint256 _maxGas,
        uint256 _gasPriceBid,
        bytes calldata _data
    ) external payable virtual override returns (bytes memory);

    function getOutboundCalldata(
        address _token,
        address _from,
        address _to,
        uint256 _amount,
        bytes memory _data
    ) public view virtual returns (bytes memory);

    function finalizeInboundTransfer(
        address _token,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    ) external payable virtual override returns (bytes memory);
}

File 13 of 14 : IGatewayRouter.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "./ITokenGateway.sol";

interface IGatewayRouter is ITokenGateway {
    function isRouter() external view returns (bool);
}

File 14 of 14 : ITokenGateway.sol
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

interface ITokenGateway {
    event OutboundTransferInitiated(
        address token,
        address indexed _from,
        address indexed _to,
        uint256 indexed _transferId,
        uint256 _amount,
        bytes _data
    );

    event InboundTransferFinalized(
        address token,
        address indexed _from,
        address indexed _to,
        uint256 indexed _transferId,
        uint256 _amount,
        bytes _data
    );

    function outboundTransfer(
        address _token,
        address _to,
        uint256 _amount,
        uint256 _maxGas,
        uint256 _gasPriceBid,
        bytes calldata _data
    ) external payable returns (bytes memory);

    function finalizeInboundTransfer(
        address _token,
        address _from,
        address _to,
        uint256 _amount,
        bytes calldata _data
    ) external payable returns (bytes memory);

    function calculateL2TokenAddress(address l1ERC20) external view returns (address);
}

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

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newDefaultGateway","type":"address"}],"name":"DefaultGatewayUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"l1Token","type":"address"},{"indexed":true,"internalType":"address","name":"gateway","type":"address"}],"name":"GatewaySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_transferId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"}],"name":"InboundTransferFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_transferId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"}],"name":"OutboundTransferInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"_userFrom","type":"address"},{"indexed":true,"internalType":"address","name":"_userTo","type":"address"},{"indexed":false,"internalType":"address","name":"gateway","type":"address"}],"name":"TransferRouted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_seqNum","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"}],"name":"TxToL2","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSource","type":"address"}],"name":"WhitelistSourceUpdated","type":"event"},{"inputs":[],"name":"STORAGE_GAP","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"l1ERC20","type":"address"}],"name":"calculateL2TokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"counterpartGateway","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultGateway","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","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":"finalizeInboundTransfer","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getGateway","outputs":[{"internalType":"address","name":"gateway","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","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":"getOutboundCalldata","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_defaultGateway","type":"address"},{"internalType":"address","name":"_whitelist","type":"address"},{"internalType":"address","name":"_counterpartGateway","type":"address"},{"internalType":"address","name":"_inbox","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isRouter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"l1TokenToGateway","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_maxGas","type":"uint256"},{"internalType":"uint256","name":"_gasPriceBid","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"outboundTransfer","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newL1DefaultGateway","type":"address"},{"internalType":"uint256","name":"_maxGas","type":"uint256"},{"internalType":"uint256","name":"_gasPriceBid","type":"uint256"},{"internalType":"uint256","name":"_maxSubmissionCost","type":"uint256"}],"name":"setDefaultGateway","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_gateway","type":"address"},{"internalType":"uint256","name":"_maxGas","type":"uint256"},{"internalType":"uint256","name":"_gasPriceBid","type":"uint256"},{"internalType":"uint256","name":"_maxSubmissionCost","type":"uint256"}],"name":"setGateway","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_token","type":"address[]"},{"internalType":"address[]","name":"_gateway","type":"address[]"},{"internalType":"uint256","name":"_maxGas","type":"uint256"},{"internalType":"uint256","name":"_gasPriceBid","type":"uint256"},{"internalType":"uint256","name":"_maxSubmissionCost","type":"uint256"}],"name":"setGateways","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSource","type":"address"}],"name":"updateWhitelistSource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b506118b2806100206000396000f3fe6080604052600436106101045760003560e01c80638da5cb5b116100a0578063d2ce7d6511610064578063d2ce7d6514610621578063dd614569146106bb578063ed08fdc6146106f3578063f398744c14610726578063fb0e722b1461073b57610104565b80638da5cb5b146104b857806393e59dc1146104cd578063a0c76a96146104e2578063a7e28d48146105bb578063bda009fe146105ee57610104565b8063032958021461010957806313af40351461013a5780631459457a1461016f5780632db09c1c146101c45780632e567b36146101d957806347466f98146102e45780635625a9521461031757806363851c3114610361578063658b53f41461038a575b600080fd5b34801561011557600080fd5b5061011e610750565b604080516001600160a01b039092168252519081900360200190f35b34801561014657600080fd5b5061016d6004803603602081101561015d57600080fd5b50356001600160a01b031661075f565b005b34801561017b57600080fd5b5061016d600480360360a081101561019257600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013582169160809091013516610818565b3480156101d057600080fd5b5061011e610864565b61026f600480360360a08110156101ef57600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b81111561023157600080fd5b82018360208201111561024357600080fd5b803590602001918460018302840111600160201b8311171561026457600080fd5b509092509050610873565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102a9578181015183820152602001610291565b50505050905090810190601f1680156102d65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102f057600080fd5b5061016d6004803603602081101561030757600080fd5b50356001600160a01b03166108b9565b61034f6004803603608081101561032d57600080fd5b506001600160a01b03813516906020810135906040810135906060013561095c565b60408051918252519081900360200190f35b34801561036d57600080fd5b50610376610ad2565b604080519115158252519081900360200190f35b61034f600480360360a08110156103a057600080fd5b810190602081018135600160201b8111156103ba57600080fd5b8201836020820111156103cc57600080fd5b803590602001918460208302840111600160201b831117156103ed57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561043c57600080fd5b82018360208201111561044e57600080fd5b803590602001918460208302840111600160201b8311171561046f57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060208101359060400135610ad7565b3480156104c457600080fd5b5061011e610b3d565b3480156104d957600080fd5b5061011e610b4c565b3480156104ee57600080fd5b5061026f600480360360a081101561050557600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b81111561054757600080fd5b82018360208201111561055957600080fd5b803590602001918460018302840111600160201b8311171561057a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610b5b945050505050565b3480156105c757600080fd5b5061011e600480360360208110156105de57600080fd5b50356001600160a01b0316610c03565b3480156105fa57600080fd5b5061011e6004803603602081101561061157600080fd5b50356001600160a01b0316610c14565b61026f600480360360c081101561063757600080fd5b6001600160a01b0382358116926020810135909116916040820135916060810135916080820135919081019060c0810160a0820135600160201b81111561067d57600080fd5b82018360208201111561068f57600080fd5b803590602001918460018302840111600160201b831117156106b057600080fd5b509092509050610ceb565b61034f600480360360808110156106d157600080fd5b506001600160a01b038135169060208101359060408101359060600135610dd4565b3480156106ff57600080fd5b5061011e6004803603602081101561071657600080fd5b50356001600160a01b0316610f21565b34801561073257600080fd5b5061011e610f3c565b34801561074757600080fd5b5061011e610f4b565b6004546001600160a01b031681565b6005546001600160a01b031633146107ab576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b6001600160a01b0381166107f6576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa7aba722a960991b604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6108228285610f5a565b600580546001600160a01b03199081166001600160a01b0397881617909155600080548216948716949094179093556006805490931694169390931790555050565b6001546001600160a01b031681565b6040805162461bcd60e51b815260206004820152601460248201527327a7262cafa7aaaa2127aaa7222fa927aaaa22a960611b6044820152905160609181900360640190fd5b6000546001600160a01b03163314610908576040805162461bcd60e51b815260206004820152600d60248201526c1393d517d19493d357d31254d5609a1b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f37389c47920d5cc3229678a0205d0455002c07541a4139ebdce91ac2274657779181900360200190a150565b6005546000906001600160a01b031633146109ab576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b600480546001600160a01b0387166001600160a01b0319909116811790915560408051918252517f3a8f8eb961383a94d41d193e16a3af73eaddfd5764a4c640257323a1603ac3319181900360200190a160006001600160a01b03861615610a7557856001600160a01b0316632db09c1c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610a4657600080fd5b505afa158015610a5a573d6000803e3d6000fd5b505050506040513d6020811015610a7057600080fd5b505190505b604080516001600160a01b0383166024808301919091528251808303909101815260449091019091526020810180516001600160e01b031663f7c9362f60e01b179052610ac733600086898986610f88565b979650505050505050565b600190565b6005546000906001600160a01b03163314610b26576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b610b338686868686610fad565b9695505050505050565b6005546001600160a01b031681565b6000546001600160a01b031681565b6060848260405160200180836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610bb7578181015183820152602001610b9f565b50505050905090810190601f168015610be45780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190529a9950505050505050505050565b6000610c0e82611296565b92915050565b6001600160a01b03808216600090815260036020526040902054166001811415610c71576040805162461bcd60e51b815260206004820152600960248201526810931050d2d31254d560ba1b604482015290519081900360640190fd5b6001600160a01b038116610c8d57506004546001600160a01b03165b610c9f816001600160a01b0316611328565b610ce6576040805162461bcd60e51b81526020600482015260136024820152721393d7d1d0551155d05657d111541313d65151606a1b604482015290519081900360640190fd5b919050565b6000546060906001600160a01b031615610db9576000546040805163babcc53960e01b815233600482015290516001600160a01b039092169163babcc53991602480820192602092909190829003018186803b158015610d4a57600080fd5b505afa158015610d5e573d6000803e3d6000fd5b505050506040513d6020811015610d7457600080fd5b5051610db9576040805162461bcd60e51b815260206004820152600f60248201526e1393d517d5d2125511531254d51151608a1b604482015290519081900360640190fd5b610dc88888888888888861132e565b50979650505050505050565b6000610ddf33611328565b610e24576040805162461bcd60e51b81526020600482015260116024820152701393d517d19493d357d0d3d395149050d5607a1b604482015290519081900360640190fd5b610e36856001600160a01b0316611328565b610e79576040805162461bcd60e51b815260206004820152600f60248201526e1393d517d513d7d0d3d395149050d5608a1b604482015290519081900360640190fd5b604080516001808252818301909252606091602080830190803683370190505090503381600081518110610ea957fe5b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526060918160200160208202803683370190505090508681600081518110610ef457fe5b60200260200101906001600160a01b031690816001600160a01b031681525050610ac78282888888610fad565b6003602052600090815260409020546001600160a01b031681565b6002546001600160a01b031681565b6006546001600160a01b031681565b610f658260006115bb565b600480546001600160a01b0319166001600160a01b039290921691909117905550565b600654600154600091610ac7916001600160a01b03918216911689898989898961167c565b60008451865114610ff4576040805162461bcd60e51b815260206004820152600c60248201526b0aea49e9c8ebe988a9c8ea8960a31b604482015290519081900360640190fd5b60005b86518110156111b25785818151811061100c57fe5b60200260200101516003600089848151811061102457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555085818151811061107c57fe5b60200260200101516001600160a01b031687828151811061109957fe5b60200260200101516001600160a01b03167f812ca95fe4492a9e2d1f2723c2c40c03a60a27b059581ae20ac4e4d73bfba35460405160405180910390a360006001600160a01b03168682815181106110ed57fe5b60200260200101516001600160a01b0316146111aa5785818151811061110f57fe5b60200260200101516001600160a01b0316632db09c1c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561114f57600080fd5b505afa158015611163573d6000803e3d6000fd5b505050506040513d602081101561117957600080fd5b5051865187908390811061118957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101610ff7565b506060634201f98560e01b8787604051602401808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156112065781810151838201526020016111ee565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561124557818101518382015260200161122d565b50505050905001945050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050610ac733600085888886610f88565b60006112a182610c14565b6001600160a01b031663a7e28d48836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156112f657600080fd5b505afa15801561130a573d6000803e3d6000fd5b505050506040513d602081101561132057600080fd5b505192915050565b3b151590565b6060600061133b89610c14565b905060606113828a338b8b89898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610b5b92505050565b604080516001600160a01b0385811682529151929350818c169233928e16917f85291dff2161a93c2f12c819d31889c96c63042116f5bc5a205aa701c2c429f5919081900360200190a4816001600160a01b031663d2ce7d65348c8c8c8c8c886040518863ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b0316815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611470578181015183820152602001611458565b50505050905090810190601f16801561149d5780820380516001836020036101000a031916815260200191505b509750505050505050506000604051808303818588803b1580156114c057600080fd5b505af11580156114d4573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405260208110156114fe57600080fd5b8101908080516040519392919084600160201b82111561151d57600080fd5b90830190602082018581111561153257600080fd5b8251600160201b81118282018810171561154b57600080fd5b82525081516020918201929091019080838360005b83811015611578578181015183820152602001611560565b50505050905090810190601f1680156115a55780820380516001836020036101000a031916815260200191505b5060405250505092505050979650505050505050565b6001600160a01b03821661160c576040805162461bcd60e51b81526020600482015260136024820152721253959053125117d0d3d55395115494105495606a1b604482015290519081900360640190fd5b6001546001600160a01b031615611659576040805162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015290519081900360640190fd5b50600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080896001600160a01b031663679b6ded348b8a8a8d8e8c8c8c6040518a63ffffffff1660e01b815260040180896001600160a01b03166001600160a01b03168152602001888152602001878152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561174357818101518382015260200161172b565b50505050905090810190601f1680156117705780820380516001836020036101000a031916815260200191505b5099505050505050505050506020604051808303818588803b15801561179557600080fd5b505af11580156117a9573d6000803e3d6000fd5b50505050506040513d60208110156117c057600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808f1694908e16937fc1d1490cf25c3b40d600dfb27c7680340ed1ab901b7e8f3551280968a3b372b0938a93919283929083019185019080838360005b8381101561183557818101518382015260200161181d565b50505050905090810190601f1680156118625780820380516001836020036101000a031916815260200191505b509250505060405180910390a4999850505050505050505056fea2646970667358221220425870ec6e3650cf2e726cc63365d60da283bc5c9045b1924d4f3f0e5eb9800e64736f6c634300060b0033

Deployed Bytecode

0x6080604052600436106101045760003560e01c80638da5cb5b116100a0578063d2ce7d6511610064578063d2ce7d6514610621578063dd614569146106bb578063ed08fdc6146106f3578063f398744c14610726578063fb0e722b1461073b57610104565b80638da5cb5b146104b857806393e59dc1146104cd578063a0c76a96146104e2578063a7e28d48146105bb578063bda009fe146105ee57610104565b8063032958021461010957806313af40351461013a5780631459457a1461016f5780632db09c1c146101c45780632e567b36146101d957806347466f98146102e45780635625a9521461031757806363851c3114610361578063658b53f41461038a575b600080fd5b34801561011557600080fd5b5061011e610750565b604080516001600160a01b039092168252519081900360200190f35b34801561014657600080fd5b5061016d6004803603602081101561015d57600080fd5b50356001600160a01b031661075f565b005b34801561017b57600080fd5b5061016d600480360360a081101561019257600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013582169160809091013516610818565b3480156101d057600080fd5b5061011e610864565b61026f600480360360a08110156101ef57600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b81111561023157600080fd5b82018360208201111561024357600080fd5b803590602001918460018302840111600160201b8311171561026457600080fd5b509092509050610873565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102a9578181015183820152602001610291565b50505050905090810190601f1680156102d65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102f057600080fd5b5061016d6004803603602081101561030757600080fd5b50356001600160a01b03166108b9565b61034f6004803603608081101561032d57600080fd5b506001600160a01b03813516906020810135906040810135906060013561095c565b60408051918252519081900360200190f35b34801561036d57600080fd5b50610376610ad2565b604080519115158252519081900360200190f35b61034f600480360360a08110156103a057600080fd5b810190602081018135600160201b8111156103ba57600080fd5b8201836020820111156103cc57600080fd5b803590602001918460208302840111600160201b831117156103ed57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561043c57600080fd5b82018360208201111561044e57600080fd5b803590602001918460208302840111600160201b8311171561046f57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060208101359060400135610ad7565b3480156104c457600080fd5b5061011e610b3d565b3480156104d957600080fd5b5061011e610b4c565b3480156104ee57600080fd5b5061026f600480360360a081101561050557600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b81111561054757600080fd5b82018360208201111561055957600080fd5b803590602001918460018302840111600160201b8311171561057a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610b5b945050505050565b3480156105c757600080fd5b5061011e600480360360208110156105de57600080fd5b50356001600160a01b0316610c03565b3480156105fa57600080fd5b5061011e6004803603602081101561061157600080fd5b50356001600160a01b0316610c14565b61026f600480360360c081101561063757600080fd5b6001600160a01b0382358116926020810135909116916040820135916060810135916080820135919081019060c0810160a0820135600160201b81111561067d57600080fd5b82018360208201111561068f57600080fd5b803590602001918460018302840111600160201b831117156106b057600080fd5b509092509050610ceb565b61034f600480360360808110156106d157600080fd5b506001600160a01b038135169060208101359060408101359060600135610dd4565b3480156106ff57600080fd5b5061011e6004803603602081101561071657600080fd5b50356001600160a01b0316610f21565b34801561073257600080fd5b5061011e610f3c565b34801561074757600080fd5b5061011e610f4b565b6004546001600160a01b031681565b6005546001600160a01b031633146107ab576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b6001600160a01b0381166107f6576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa7aba722a960991b604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6108228285610f5a565b600580546001600160a01b03199081166001600160a01b0397881617909155600080548216948716949094179093556006805490931694169390931790555050565b6001546001600160a01b031681565b6040805162461bcd60e51b815260206004820152601460248201527327a7262cafa7aaaa2127aaa7222fa927aaaa22a960611b6044820152905160609181900360640190fd5b6000546001600160a01b03163314610908576040805162461bcd60e51b815260206004820152600d60248201526c1393d517d19493d357d31254d5609a1b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f37389c47920d5cc3229678a0205d0455002c07541a4139ebdce91ac2274657779181900360200190a150565b6005546000906001600160a01b031633146109ab576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b600480546001600160a01b0387166001600160a01b0319909116811790915560408051918252517f3a8f8eb961383a94d41d193e16a3af73eaddfd5764a4c640257323a1603ac3319181900360200190a160006001600160a01b03861615610a7557856001600160a01b0316632db09c1c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610a4657600080fd5b505afa158015610a5a573d6000803e3d6000fd5b505050506040513d6020811015610a7057600080fd5b505190505b604080516001600160a01b0383166024808301919091528251808303909101815260449091019091526020810180516001600160e01b031663f7c9362f60e01b179052610ac733600086898986610f88565b979650505050505050565b600190565b6005546000906001600160a01b03163314610b26576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b610b338686868686610fad565b9695505050505050565b6005546001600160a01b031681565b6000546001600160a01b031681565b6060848260405160200180836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610bb7578181015183820152602001610b9f565b50505050905090810190601f168015610be45780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190529a9950505050505050505050565b6000610c0e82611296565b92915050565b6001600160a01b03808216600090815260036020526040902054166001811415610c71576040805162461bcd60e51b815260206004820152600960248201526810931050d2d31254d560ba1b604482015290519081900360640190fd5b6001600160a01b038116610c8d57506004546001600160a01b03165b610c9f816001600160a01b0316611328565b610ce6576040805162461bcd60e51b81526020600482015260136024820152721393d7d1d0551155d05657d111541313d65151606a1b604482015290519081900360640190fd5b919050565b6000546060906001600160a01b031615610db9576000546040805163babcc53960e01b815233600482015290516001600160a01b039092169163babcc53991602480820192602092909190829003018186803b158015610d4a57600080fd5b505afa158015610d5e573d6000803e3d6000fd5b505050506040513d6020811015610d7457600080fd5b5051610db9576040805162461bcd60e51b815260206004820152600f60248201526e1393d517d5d2125511531254d51151608a1b604482015290519081900360640190fd5b610dc88888888888888861132e565b50979650505050505050565b6000610ddf33611328565b610e24576040805162461bcd60e51b81526020600482015260116024820152701393d517d19493d357d0d3d395149050d5607a1b604482015290519081900360640190fd5b610e36856001600160a01b0316611328565b610e79576040805162461bcd60e51b815260206004820152600f60248201526e1393d517d513d7d0d3d395149050d5608a1b604482015290519081900360640190fd5b604080516001808252818301909252606091602080830190803683370190505090503381600081518110610ea957fe5b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526060918160200160208202803683370190505090508681600081518110610ef457fe5b60200260200101906001600160a01b031690816001600160a01b031681525050610ac78282888888610fad565b6003602052600090815260409020546001600160a01b031681565b6002546001600160a01b031681565b6006546001600160a01b031681565b610f658260006115bb565b600480546001600160a01b0319166001600160a01b039290921691909117905550565b600654600154600091610ac7916001600160a01b03918216911689898989898961167c565b60008451865114610ff4576040805162461bcd60e51b815260206004820152600c60248201526b0aea49e9c8ebe988a9c8ea8960a31b604482015290519081900360640190fd5b60005b86518110156111b25785818151811061100c57fe5b60200260200101516003600089848151811061102457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555085818151811061107c57fe5b60200260200101516001600160a01b031687828151811061109957fe5b60200260200101516001600160a01b03167f812ca95fe4492a9e2d1f2723c2c40c03a60a27b059581ae20ac4e4d73bfba35460405160405180910390a360006001600160a01b03168682815181106110ed57fe5b60200260200101516001600160a01b0316146111aa5785818151811061110f57fe5b60200260200101516001600160a01b0316632db09c1c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561114f57600080fd5b505afa158015611163573d6000803e3d6000fd5b505050506040513d602081101561117957600080fd5b5051865187908390811061118957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101610ff7565b506060634201f98560e01b8787604051602401808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156112065781810151838201526020016111ee565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561124557818101518382015260200161122d565b50505050905001945050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050610ac733600085888886610f88565b60006112a182610c14565b6001600160a01b031663a7e28d48836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156112f657600080fd5b505afa15801561130a573d6000803e3d6000fd5b505050506040513d602081101561132057600080fd5b505192915050565b3b151590565b6060600061133b89610c14565b905060606113828a338b8b89898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610b5b92505050565b604080516001600160a01b0385811682529151929350818c169233928e16917f85291dff2161a93c2f12c819d31889c96c63042116f5bc5a205aa701c2c429f5919081900360200190a4816001600160a01b031663d2ce7d65348c8c8c8c8c886040518863ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b0316815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611470578181015183820152602001611458565b50505050905090810190601f16801561149d5780820380516001836020036101000a031916815260200191505b509750505050505050506000604051808303818588803b1580156114c057600080fd5b505af11580156114d4573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405260208110156114fe57600080fd5b8101908080516040519392919084600160201b82111561151d57600080fd5b90830190602082018581111561153257600080fd5b8251600160201b81118282018810171561154b57600080fd5b82525081516020918201929091019080838360005b83811015611578578181015183820152602001611560565b50505050905090810190601f1680156115a55780820380516001836020036101000a031916815260200191505b5060405250505092505050979650505050505050565b6001600160a01b03821661160c576040805162461bcd60e51b81526020600482015260136024820152721253959053125117d0d3d55395115494105495606a1b604482015290519081900360640190fd5b6001546001600160a01b031615611659576040805162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015290519081900360640190fd5b50600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080896001600160a01b031663679b6ded348b8a8a8d8e8c8c8c6040518a63ffffffff1660e01b815260040180896001600160a01b03166001600160a01b03168152602001888152602001878152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561174357818101518382015260200161172b565b50505050905090810190601f1680156117705780820380516001836020036101000a031916815260200191505b5099505050505050505050506020604051808303818588803b15801561179557600080fd5b505af11580156117a9573d6000803e3d6000fd5b50505050506040513d60208110156117c057600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808f1694908e16937fc1d1490cf25c3b40d600dfb27c7680340ed1ab901b7e8f3551280968a3b372b0938a93919283929083019185019080838360005b8381101561183557818101518382015260200161181d565b50505050905090810190601f1680156118625780820380516001836020036101000a031916815260200191505b509250505060405180910390a4999850505050505050505056fea2646970667358221220425870ec6e3650cf2e726cc63365d60da283bc5c9045b1924d4f3f0e5eb9800e64736f6c634300060b0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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.