{
  "language": "Solidity",
  "sources": {
    "contracts/L1/messaging/IL1CrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\n\n/* Interface Imports */\nimport { ICrossDomainMessenger } from \"../../libraries/bridge/ICrossDomainMessenger.sol\";\n\n/**\n * @title IL1CrossDomainMessenger\n */\ninterface IL1CrossDomainMessenger is ICrossDomainMessenger {\n    /*******************\n     * Data Structures *\n     *******************/\n\n    struct L2MessageInclusionProof {\n        bytes32 stateRoot;\n        Lib_OVMCodec.ChainBatchHeader stateRootBatchHeader;\n        Lib_OVMCodec.ChainInclusionProof stateRootProof;\n        bytes stateTrieWitness;\n        bytes storageTrieWitness;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Relays a cross domain message to a contract.\n     * @param _target Target contract address.\n     * @param _sender Message sender address.\n     * @param _message Message to send to the target.\n     * @param _messageNonce Nonce for the provided message.\n     * @param _proof Inclusion proof for the given message.\n     */\n    function relayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce,\n        L2MessageInclusionProof memory _proof\n    ) external;\n\n    /**\n     * Replays a cross domain message to the target messenger.\n     * @param _target Target contract address.\n     * @param _sender Original sender address.\n     * @param _message Message to send to the target.\n     * @param _queueIndex CTC Queue index for the message to replay.\n     * @param _oldGasLimit Original gas limit used to send the message.\n     * @param _newGasLimit New gas limit to be used for this message.\n     */\n    function replayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _queueIndex,\n        uint32 _oldGasLimit,\n        uint32 _newGasLimit\n    ) external;\n\n    /**\n     * Relays a cross domain message to a contract with L2 chain id.\n     * @param _chainId L2 chain id.\n     * @param _target Target contract address.\n     * @param _sender Message sender address.\n     * @param _message Message to send to the target.\n     * @param _messageNonce Nonce for the provided message.\n     * @param _proof Inclusion proof for the given message.\n     */\n    function relayMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce,\n        L2MessageInclusionProof memory _proof\n    ) external;\n\n    /**\n     * Replays a cross domain message to the target messenger with L2 chain id.\n     * @param _chainId L2 chain id.\n     * @param _target Target contract address.\n     * @param _sender Original sender address.\n     * @param _message Message to send to the target.\n     * @param _oldGasLimit Original gas limit used to send the message.\n     * @param _newGasLimit New gas limit to be used for this message.\n     */\n    function replayMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _queueIndex,\n        uint32 _oldGasLimit,\n        uint32 _newGasLimit\n    ) external;\n}\n"
    },
    "contracts/libraries/codec/Lib_OVMCodec.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_RLPReader } from \"../rlp/Lib_RLPReader.sol\";\n\n/**\n * @title Lib_OVMCodec\n */\nlibrary Lib_OVMCodec {\n    /*********\n     * Enums *\n     *********/\n\n    enum QueueOrigin {\n        SEQUENCER_QUEUE,\n        L1TOL2_QUEUE\n    }\n\n    /***********\n     * Structs *\n     ***********/\n\n    struct EVMAccount {\n        uint256 nonce;\n        uint256 balance;\n        bytes32 storageRoot;\n        bytes32 codeHash;\n    }\n\n    struct ChainBatchHeader {\n        uint256 batchIndex;\n        bytes32 batchRoot;\n        uint256 batchSize;\n        uint256 prevTotalElements;\n        bytes extraData;\n    }\n\n    struct ChainInclusionProof {\n        uint256 index;\n        bytes32[] siblings;\n    }\n\n    struct Transaction {\n        uint256 timestamp;\n        uint256 blockNumber;\n        QueueOrigin l1QueueOrigin;\n        address l1TxOrigin;\n        address entrypoint;\n        uint256 gasLimit;\n        bytes data;\n    }\n\n    struct TransactionChainElement {\n        bool isSequenced;\n        uint256 queueIndex; // QUEUED TX ONLY\n        uint256 timestamp; // SEQUENCER TX ONLY\n        uint256 blockNumber; // SEQUENCER TX ONLY\n        bytes txData; // SEQUENCER TX ONLY\n    }\n\n    struct QueueElement {\n        bytes32 transactionHash;\n        uint40 timestamp;\n        uint40 blockNumber;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Encodes a standard OVM transaction.\n     * @param _transaction OVM transaction to encode.\n     * @return Encoded transaction bytes.\n     */\n    function encodeTransaction(Transaction memory _transaction)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return\n            abi.encodePacked(\n                _transaction.timestamp,\n                _transaction.blockNumber,\n                _transaction.l1QueueOrigin,\n                _transaction.l1TxOrigin,\n                _transaction.entrypoint,\n                _transaction.gasLimit,\n                _transaction.data\n            );\n    }\n\n    /**\n     * Hashes a standard OVM transaction.\n     * @param _transaction OVM transaction to encode.\n     * @return Hashed transaction\n     */\n    function hashTransaction(Transaction memory _transaction) internal pure returns (bytes32) {\n        return keccak256(encodeTransaction(_transaction));\n    }\n\n    /**\n     * @notice Decodes an RLP-encoded account state into a useful struct.\n     * @param _encoded RLP-encoded account state.\n     * @return Account state struct.\n     */\n    function decodeEVMAccount(bytes memory _encoded) internal pure returns (EVMAccount memory) {\n        Lib_RLPReader.RLPItem[] memory accountState = Lib_RLPReader.readList(_encoded);\n\n        return\n            EVMAccount({\n                nonce: Lib_RLPReader.readUint256(accountState[0]),\n                balance: Lib_RLPReader.readUint256(accountState[1]),\n                storageRoot: Lib_RLPReader.readBytes32(accountState[2]),\n                codeHash: Lib_RLPReader.readBytes32(accountState[3])\n            });\n    }\n\n    /**\n     * Calculates a hash for a given batch header.\n     * @param _batchHeader Header to hash.\n     * @return Hash of the header.\n     */\n    function hashBatchHeader(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)\n        internal\n        pure\n        returns (bytes32)\n    {\n        return\n            keccak256(\n                abi.encode(\n                    _batchHeader.batchRoot,\n                    _batchHeader.batchSize,\n                    _batchHeader.prevTotalElements,\n                    _batchHeader.extraData\n                )\n            );\n    }\n}\n"
    },
    "contracts/libraries/bridge/ICrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title ICrossDomainMessenger\n */\ninterface ICrossDomainMessenger {\n    /**********\n     * Events *\n     **********/\n\n    event SentMessage(\n        address indexed target,\n        address sender,\n        bytes message,\n        uint256 messageNonce,\n        uint256 gasLimit,\n        uint256 chainId\n    );\n    event RelayedMessage(bytes32 indexed msgHash);\n    event FailedRelayedMessage(bytes32 indexed msgHash);\n\n    /*************\n     * Variables *\n     *************/\n\n    function xDomainMessageSender() external view returns (address);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Sends a cross domain message to the target messenger.\n     * @param _target Target contract address.\n     * @param _message Message to send to the target.\n     * @param _gasLimit Gas limit for the provided message.\n     */\n    function sendMessage(\n        address _target,\n        bytes calldata _message,\n        uint32 _gasLimit\n    ) external payable;\n\n    /**\n     * Sends a cross domain message to the target messenger.\n     * @param _chainId L2 chain id.\n     * @param _target Target contract address.\n     * @param _message Message to send to the target.\n     * @param _gasLimit Gas limit for the provided message.\n     */\n    function sendMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        bytes calldata _message,\n        uint32 _gasLimit\n    ) external payable;\n}\n"
    },
    "contracts/libraries/rlp/Lib_RLPReader.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_RLPReader\n * @dev Adapted from \"RLPReader\" by Hamdi Allam (hamdi.allam97@gmail.com).\n */\nlibrary Lib_RLPReader {\n    /*************\n     * Constants *\n     *************/\n\n    uint256 internal constant MAX_LIST_LENGTH = 32;\n\n    /*********\n     * Enums *\n     *********/\n\n    enum RLPItemType {\n        DATA_ITEM,\n        LIST_ITEM\n    }\n\n    /***********\n     * Structs *\n     ***********/\n\n    struct RLPItem {\n        uint256 length;\n        uint256 ptr;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Converts bytes to a reference to memory position and length.\n     * @param _in Input bytes to convert.\n     * @return Output memory reference.\n     */\n    function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {\n        uint256 ptr;\n        assembly {\n            ptr := add(_in, 32)\n        }\n\n        return RLPItem({ length: _in.length, ptr: ptr });\n    }\n\n    /**\n     * Reads an RLP list value into a list of RLP items.\n     * @param _in RLP list value.\n     * @return Decoded RLP list items.\n     */\n    function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {\n        (uint256 listOffset, , RLPItemType itemType) = _decodeLength(_in);\n\n        require(itemType == RLPItemType.LIST_ITEM, \"Invalid RLP list value.\");\n\n        // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n        // writing to the length. Since we can't know the number of RLP items without looping over\n        // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n        // simply set a reasonable maximum list length and decrease the size before we finish.\n        RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);\n\n        uint256 itemCount = 0;\n        uint256 offset = listOffset;\n        while (offset < _in.length) {\n            require(itemCount < MAX_LIST_LENGTH, \"Provided RLP list exceeds max list length.\");\n\n            (uint256 itemOffset, uint256 itemLength, ) = _decodeLength(\n                RLPItem({ length: _in.length - offset, ptr: _in.ptr + offset })\n            );\n\n            out[itemCount] = RLPItem({ length: itemLength + itemOffset, ptr: _in.ptr + offset });\n\n            itemCount += 1;\n            offset += itemOffset + itemLength;\n        }\n\n        // Decrease the array size to match the actual item count.\n        assembly {\n            mstore(out, itemCount)\n        }\n\n        return out;\n    }\n\n    /**\n     * Reads an RLP list value into a list of RLP items.\n     * @param _in RLP list value.\n     * @return Decoded RLP list items.\n     */\n    function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {\n        return readList(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP bytes value into bytes.\n     * @param _in RLP bytes value.\n     * @return Decoded bytes.\n     */\n    function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n        (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n        require(itemType == RLPItemType.DATA_ITEM, \"Invalid RLP bytes value.\");\n\n        return _copy(_in.ptr, itemOffset, itemLength);\n    }\n\n    /**\n     * Reads an RLP bytes value into bytes.\n     * @param _in RLP bytes value.\n     * @return Decoded bytes.\n     */\n    function readBytes(bytes memory _in) internal pure returns (bytes memory) {\n        return readBytes(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP string value into a string.\n     * @param _in RLP string value.\n     * @return Decoded string.\n     */\n    function readString(RLPItem memory _in) internal pure returns (string memory) {\n        return string(readBytes(_in));\n    }\n\n    /**\n     * Reads an RLP string value into a string.\n     * @param _in RLP string value.\n     * @return Decoded string.\n     */\n    function readString(bytes memory _in) internal pure returns (string memory) {\n        return readString(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP bytes32 value into a bytes32.\n     * @param _in RLP bytes32 value.\n     * @return Decoded bytes32.\n     */\n    function readBytes32(RLPItem memory _in) internal pure returns (bytes32) {\n        require(_in.length <= 33, \"Invalid RLP bytes32 value.\");\n\n        (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n        require(itemType == RLPItemType.DATA_ITEM, \"Invalid RLP bytes32 value.\");\n\n        uint256 ptr = _in.ptr + itemOffset;\n        bytes32 out;\n        assembly {\n            out := mload(ptr)\n\n            // Shift the bytes over to match the item size.\n            if lt(itemLength, 32) {\n                out := div(out, exp(256, sub(32, itemLength)))\n            }\n        }\n\n        return out;\n    }\n\n    /**\n     * Reads an RLP bytes32 value into a bytes32.\n     * @param _in RLP bytes32 value.\n     * @return Decoded bytes32.\n     */\n    function readBytes32(bytes memory _in) internal pure returns (bytes32) {\n        return readBytes32(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP uint256 value into a uint256.\n     * @param _in RLP uint256 value.\n     * @return Decoded uint256.\n     */\n    function readUint256(RLPItem memory _in) internal pure returns (uint256) {\n        return uint256(readBytes32(_in));\n    }\n\n    /**\n     * Reads an RLP uint256 value into a uint256.\n     * @param _in RLP uint256 value.\n     * @return Decoded uint256.\n     */\n    function readUint256(bytes memory _in) internal pure returns (uint256) {\n        return readUint256(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP bool value into a bool.\n     * @param _in RLP bool value.\n     * @return Decoded bool.\n     */\n    function readBool(RLPItem memory _in) internal pure returns (bool) {\n        require(_in.length == 1, \"Invalid RLP boolean value.\");\n\n        uint256 ptr = _in.ptr;\n        uint256 out;\n        assembly {\n            out := byte(0, mload(ptr))\n        }\n\n        require(out == 0 || out == 1, \"Lib_RLPReader: Invalid RLP boolean value, must be 0 or 1\");\n\n        return out != 0;\n    }\n\n    /**\n     * Reads an RLP bool value into a bool.\n     * @param _in RLP bool value.\n     * @return Decoded bool.\n     */\n    function readBool(bytes memory _in) internal pure returns (bool) {\n        return readBool(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP address value into a address.\n     * @param _in RLP address value.\n     * @return Decoded address.\n     */\n    function readAddress(RLPItem memory _in) internal pure returns (address) {\n        if (_in.length == 1) {\n            return address(0);\n        }\n\n        require(_in.length == 21, \"Invalid RLP address value.\");\n\n        return address(uint160(readUint256(_in)));\n    }\n\n    /**\n     * Reads an RLP address value into a address.\n     * @param _in RLP address value.\n     * @return Decoded address.\n     */\n    function readAddress(bytes memory _in) internal pure returns (address) {\n        return readAddress(toRLPItem(_in));\n    }\n\n    /**\n     * Reads the raw bytes of an RLP item.\n     * @param _in RLP item to read.\n     * @return Raw RLP bytes.\n     */\n    function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n        return _copy(_in);\n    }\n\n    /*********************\n     * Private Functions *\n     *********************/\n\n    /**\n     * Decodes the length of an RLP item.\n     * @param _in RLP item to decode.\n     * @return Offset of the encoded data.\n     * @return Length of the encoded data.\n     * @return RLP item type (LIST_ITEM or DATA_ITEM).\n     */\n    function _decodeLength(RLPItem memory _in)\n        private\n        pure\n        returns (\n            uint256,\n            uint256,\n            RLPItemType\n        )\n    {\n        require(_in.length > 0, \"RLP item cannot be null.\");\n\n        uint256 ptr = _in.ptr;\n        uint256 prefix;\n        assembly {\n            prefix := byte(0, mload(ptr))\n        }\n\n        if (prefix <= 0x7f) {\n            // Single byte.\n\n            return (0, 1, RLPItemType.DATA_ITEM);\n        } else if (prefix <= 0xb7) {\n            // Short string.\n\n            uint256 strLen = prefix - 0x80;\n\n            require(_in.length > strLen, \"Invalid RLP short string.\");\n\n            return (1, strLen, RLPItemType.DATA_ITEM);\n        } else if (prefix <= 0xbf) {\n            // Long string.\n            uint256 lenOfStrLen = prefix - 0xb7;\n\n            require(_in.length > lenOfStrLen, \"Invalid RLP long string length.\");\n\n            uint256 strLen;\n            assembly {\n                // Pick out the string length.\n                strLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfStrLen)))\n            }\n\n            require(_in.length > lenOfStrLen + strLen, \"Invalid RLP long string.\");\n\n            return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n        } else if (prefix <= 0xf7) {\n            // Short list.\n            uint256 listLen = prefix - 0xc0;\n\n            require(_in.length > listLen, \"Invalid RLP short list.\");\n\n            return (1, listLen, RLPItemType.LIST_ITEM);\n        } else {\n            // Long list.\n            uint256 lenOfListLen = prefix - 0xf7;\n\n            require(_in.length > lenOfListLen, \"Invalid RLP long list length.\");\n\n            uint256 listLen;\n            assembly {\n                // Pick out the list length.\n                listLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfListLen)))\n            }\n\n            require(_in.length > lenOfListLen + listLen, \"Invalid RLP long list.\");\n\n            return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n        }\n    }\n\n    /**\n     * Copies the bytes from a memory location.\n     * @param _src Pointer to the location to read from.\n     * @param _offset Offset to start reading from.\n     * @param _length Number of bytes to read.\n     * @return Copied bytes.\n     */\n    function _copy(\n        uint256 _src,\n        uint256 _offset,\n        uint256 _length\n    ) private pure returns (bytes memory) {\n        bytes memory out = new bytes(_length);\n        if (out.length == 0) {\n            return out;\n        }\n\n        uint256 src = _src + _offset;\n        uint256 dest;\n        assembly {\n            dest := add(out, 32)\n        }\n\n        // Copy over as many complete words as we can.\n        for (uint256 i = 0; i < _length / 32; i++) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n\n            src += 32;\n            dest += 32;\n        }\n\n        // Pick out the remaining bytes.\n        uint256 mask;\n        unchecked {\n            mask = 256**(32 - (_length % 32)) - 1;\n        }\n\n        assembly {\n            mstore(dest, or(and(mload(src), not(mask)), and(mload(dest), mask)))\n        }\n        return out;\n    }\n\n    /**\n     * Copies an RLP item into bytes.\n     * @param _in RLP item to copy.\n     * @return Copied bytes.\n     */\n    function _copy(RLPItem memory _in) private pure returns (bytes memory) {\n        return _copy(_in.ptr, 0, _in.length);\n    }\n}\n"
    },
    "contracts/L1/messaging/L1CrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { AddressAliasHelper } from \"../../standards/AddressAliasHelper.sol\";\nimport { Lib_AddressResolver } from \"../../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\nimport { Lib_AddressManager } from \"../../libraries/resolver/Lib_AddressManager.sol\";\nimport { Lib_SecureMerkleTrie } from \"../../libraries/trie/Lib_SecureMerkleTrie.sol\";\nimport { Lib_DefaultValues } from \"../../libraries/constants/Lib_DefaultValues.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\nimport { Lib_CrossDomainUtils } from \"../../libraries/bridge/Lib_CrossDomainUtils.sol\";\n\n/* Interface Imports */\nimport { IL1CrossDomainMessenger } from \"./IL1CrossDomainMessenger.sol\";\nimport { ICanonicalTransactionChain } from \"../rollup/ICanonicalTransactionChain.sol\";\nimport { IStateCommitmentChain } from \"../rollup/IStateCommitmentChain.sol\";\nimport { iMVM_DiscountOracle } from \"../../MVM/iMVM_DiscountOracle.sol\";\n\n/* External Imports */\nimport {\n    OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n    PausableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {\n    ReentrancyGuardUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\n\n/**\n * @title L1CrossDomainMessenger\n * @dev The L1 Cross Domain Messenger contract sends messages from L1 to L2, and relays messages\n * from L2 onto L1. In the event that a message sent from L1 to L2 is rejected for exceeding the L2\n * epoch gas limit, it can be resubmitted via this contract's replay function.\n *\n * Runtime target: EVM\n */\ncontract L1CrossDomainMessenger is\n    IL1CrossDomainMessenger,\n    Lib_AddressResolver,\n    OwnableUpgradeable,\n    PausableUpgradeable,\n    ReentrancyGuardUpgradeable\n{\n    /**********\n     * Events *\n     **********/\n\n    event MessageBlocked(bytes32 indexed _xDomainCalldataHash);\n\n    event MessageAllowed(bytes32 indexed _xDomainCalldataHash);\n\n    /**********************\n     * Contract Variables *\n     **********************/\n\n    mapping(bytes32 => bool) public blockedMessages;\n    mapping(bytes32 => bool) public relayedMessages;\n    mapping(bytes32 => bool) public successfulMessages;\n\n    address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;\n    uint256 internal constant DEFAULT_CHAINID = 1088;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * This contract is intended to be behind a delegate proxy.\n     * We pass the zero address to the address resolver just to satisfy the constructor.\n     * We still need to set this value in initialize().\n     */\n    constructor() Lib_AddressResolver(address(0)) {}\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     */\n    function initialize(address _libAddressManager) public initializer {\n        require(\n            address(libAddressManager) == address(0),\n            \"L1CrossDomainMessenger already intialized.\"\n        );\n        libAddressManager = Lib_AddressManager(_libAddressManager);\n        xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;\n\n        // Initialize upgradable OZ contracts\n        __Context_init_unchained(); // Context is a dependency for both Ownable and Pausable\n        __Ownable_init_unchained();\n        __Pausable_init_unchained();\n        __ReentrancyGuard_init_unchained();\n    }\n\n    /**\n     * Pause relaying.\n     */\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    /**\n     * Unpause relaying.\n     */\n    function unpause() external onlyOwner {\n        _unpause();\n    }\n\n    /**\n     * Block a message.\n     * @param _xDomainCalldataHash Hash of the message to block.\n     */\n    function blockMessage(bytes32 _xDomainCalldataHash) external onlyOwner {\n        blockedMessages[_xDomainCalldataHash] = true;\n        emit MessageBlocked(_xDomainCalldataHash);\n    }\n\n    /**\n     * Allow a message.\n     * @param _xDomainCalldataHash Hash of the message to block.\n     */\n    function allowMessage(bytes32 _xDomainCalldataHash) external onlyOwner {\n        blockedMessages[_xDomainCalldataHash] = false;\n        emit MessageAllowed(_xDomainCalldataHash);\n    }\n\n    function xDomainMessageSender() external view returns (address) {\n        require(\n            xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER,\n            \"xDomainMessageSender is not set\"\n        );\n        return xDomainMsgSender;\n    }\n\n    /**\n     * Sends a cross domain message to the target messenger.\n     * only accounts checked by MVM_DiscountOracle.isXDomainSenderAllowed can send message from L1 to L2\n     * @param _target Target contract address.\n     * @param _message Message to send to the target.\n     * @param _gasLimit Gas limit for the provided message.\n     */\n    function sendMessage(\n        address _target,\n        bytes memory _message,\n        uint32 _gasLimit\n    ) external payable {\n        sendMessageViaChainId(DEFAULT_CHAINID, _target, _message, _gasLimit);\n\n        // iMVM_DiscountOracle oracle = iMVM_DiscountOracle(resolve('MVM_DiscountOracle'));\n        // // this function will check against the whitelist and take the fee\n        // oracle.processL2SeqGas{value:msg.value}(msg.sender, DEFAULT_CHAINID);\n\n        // address ovmCanonicalTransactionChain = resolve(\"CanonicalTransactionChain\");\n        // // Use the CTC queue length as nonce\n        // uint40 nonce = ICanonicalTransactionChain(ovmCanonicalTransactionChain).getQueueLength();\n\n        // bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n        //     _target,\n        //     msg.sender,\n        //     _message,\n        //     nonce\n        // );\n\n        // _sendXDomainMessage(ovmCanonicalTransactionChain, xDomainCalldata, _gasLimit);\n\n        // emit SentMessage(_target, msg.sender, _message, nonce, _gasLimit, DEFAULT_CHAINID);\n    }\n\n    /**\n     * Sends a cross domain message to the target messenger.\n     * only accounts checked by MVM_DiscountOracle.isXDomainSenderAllowed can send message from L1 to L2\n     * @param _chainId L2 chain id.\n     * @param _target Target contract address.\n     * @param _message Message to send to the target.\n     * @param _gasLimit Gas limit for the provided message.\n     */\n    function sendMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        bytes memory _message,\n        uint32 _gasLimit\n    ) public payable override {\n        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(resolve(\"MVM_DiscountOracle\"));\n\n        // this function will check against the whitelist and take the fee\n        oracle.processL2SeqGas{ value: msg.value }(msg.sender, _chainId);\n\n        address ovmCanonicalTransactionChain = resolve(\"CanonicalTransactionChain\");\n\n        // Use the CTC queue length as nonce\n        uint40 nonce = ICanonicalTransactionChain(ovmCanonicalTransactionChain)\n            .getQueueLengthByChainId(_chainId);\n\n        bytes memory xDomainCalldataRaw = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            msg.sender,\n            _message,\n            nonce\n        );\n\n        _sendXDomainMessageViaChainId(\n            _chainId,\n            ovmCanonicalTransactionChain,\n            xDomainCalldataRaw,\n            _gasLimit\n        );\n        emit SentMessage(_target, msg.sender, _message, nonce, _gasLimit, _chainId);\n    }\n\n    /**\n     * Relays a cross domain message to a contract.\n     * @inheritdoc IL1CrossDomainMessenger\n     */\n    function relayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce,\n        L2MessageInclusionProof memory _proof\n    ) external whenNotPaused {\n        relayMessageViaChainId(DEFAULT_CHAINID, _target, _sender, _message, _messageNonce, _proof);\n    }\n\n    /**\n     * Replays a cross domain message to the target messenger.\n     * @inheritdoc IL1CrossDomainMessenger\n     */\n    function replayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _queueIndex,\n        uint32 _oldGasLimit,\n        uint32 _newGasLimit\n    ) external {\n        replayMessageViaChainId(\n            DEFAULT_CHAINID,\n            _target,\n            _sender,\n            _message,\n            _queueIndex,\n            _oldGasLimit,\n            _newGasLimit\n        );\n    }\n\n    function relayMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce,\n        L2MessageInclusionProof memory _proof\n    ) public override nonReentrant whenNotPaused {\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            _sender,\n            _message,\n            _messageNonce\n        );\n        require(\n            _verifyXDomainMessageByChainId(_chainId, xDomainCalldata, _proof) == true,\n            \"Provided message could not be verified.\"\n        );\n\n        bytes32 xDomainCalldataHash = keccak256(xDomainCalldata);\n\n        require(\n            successfulMessages[xDomainCalldataHash] == false,\n            \"Provided message has already been received.\"\n        );\n\n        require(\n            blockedMessages[xDomainCalldataHash] == false,\n            \"Provided message has been blocked.\"\n        );\n\n        require(\n            _target != resolve(\"CanonicalTransactionChain\"),\n            \"Cannot send L2->L1 messages to L1 system contracts.\"\n        );\n\n        xDomainMsgSender = _sender;\n        (bool success, ) = _target.call(_message);\n        xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;\n\n        // Mark the message as received if the call was successful. Ensures that a message can be\n        // relayed multiple times in the case that the call reverted.\n        if (success) {\n            successfulMessages[xDomainCalldataHash] = true;\n            emit RelayedMessage(xDomainCalldataHash);\n        } else {\n            emit FailedRelayedMessage(xDomainCalldataHash);\n        }\n\n        // Store an identifier that can be used to prove that the given message was relayed by some\n        // user. Gives us an easy way to pay relayers for their work.\n        bytes32 relayId = keccak256(abi.encodePacked(xDomainCalldata, msg.sender, block.number));\n        relayedMessages[relayId] = true;\n    }\n\n    /**\n     * Replays a cross domain message to the target messenger.\n     *\n     */\n    function replayMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _queueIndex,\n        uint32 _oldGasLimit,\n        uint32 _newGasLimit\n    ) public override {\n        // Verify that the message is in the queue:\n        address canonicalTransactionChain = resolve(\"CanonicalTransactionChain\");\n        Lib_OVMCodec.QueueElement memory element = ICanonicalTransactionChain(\n            canonicalTransactionChain\n        ).getQueueElementByChainId(_chainId, _queueIndex);\n\n        //Compute the calldata that was originally used to send the message.\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            _sender,\n            _message,\n            _queueIndex\n        );\n\n        // Compute the transactionHash\n        bytes32 transactionHash = keccak256(\n            abi.encode(\n                AddressAliasHelper.applyL1ToL2Alias(address(this)),\n                Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,\n                _oldGasLimit,\n                xDomainCalldata\n            )\n        );\n\n        require(\n            transactionHash == element.transactionHash,\n            \"Provided message has not been enqueued.\"\n        );\n\n        _sendXDomainMessageViaChainId(\n            _chainId,\n            canonicalTransactionChain,\n            xDomainCalldata,\n            _newGasLimit\n        );\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Verifies that the given message is valid.\n     * @param _xDomainCalldata Calldata to verify.\n     * @param _proof Inclusion proof for the message.\n     * @return Whether or not the provided message is valid.\n     */\n    function _verifyXDomainMessage(\n        bytes memory _xDomainCalldata,\n        L2MessageInclusionProof memory _proof\n    ) internal view returns (bool) {\n        return (_verifyStateRootProof(_proof) && _verifyStorageProof(_xDomainCalldata, _proof));\n    }\n\n    /**\n     * Verifies that the state root within an inclusion proof is valid.\n     * @param _proof Message inclusion proof.\n     * @return Whether or not the provided proof is valid.\n     */\n    function _verifyStateRootProof(L2MessageInclusionProof memory _proof)\n        internal\n        view\n        returns (bool)\n    {\n        IStateCommitmentChain ovmStateCommitmentChain = IStateCommitmentChain(\n            resolve(\"StateCommitmentChain\")\n        );\n\n        return (!ovmStateCommitmentChain.insideFraudProofWindow(_proof.stateRootBatchHeader) &&\n            ovmStateCommitmentChain.verifyStateCommitment(\n                _proof.stateRoot,\n                _proof.stateRootBatchHeader,\n                _proof.stateRootProof\n            ));\n    }\n\n    /**\n     * Verifies that the storage proof within an inclusion proof is valid.\n     * @param _xDomainCalldata Encoded message calldata.\n     * @param _proof Message inclusion proof.\n     * @return Whether or not the provided proof is valid.\n     */\n    function _verifyStorageProof(\n        bytes memory _xDomainCalldata,\n        L2MessageInclusionProof memory _proof\n    ) internal pure returns (bool) {\n        bytes32 storageKey = keccak256(\n            abi.encodePacked(\n                keccak256(\n                    abi.encodePacked(\n                        _xDomainCalldata,\n                        Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER\n                    )\n                ),\n                uint256(0)\n            )\n        );\n\n        (bool exists, bytes memory encodedMessagePassingAccount) = Lib_SecureMerkleTrie.get(\n            abi.encodePacked(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER),\n            _proof.stateTrieWitness,\n            _proof.stateRoot\n        );\n\n        require(\n            exists,\n            \"Message passing predeploy has not been initialized or invalid proof provided.\"\n        );\n\n        Lib_OVMCodec.EVMAccount memory account = Lib_OVMCodec.decodeEVMAccount(\n            encodedMessagePassingAccount\n        );\n\n        return\n            Lib_SecureMerkleTrie.verifyInclusionProof(\n                abi.encodePacked(storageKey),\n                abi.encodePacked(uint8(1)),\n                _proof.storageTrieWitness,\n                account.storageRoot\n            );\n    }\n\n    /**\n     * Sends a cross domain message.\n     * @param _canonicalTransactionChain Address of the CanonicalTransactionChain instance.\n     * @param _message Message to send.\n     * @param _gasLimit OVM gas limit for the message.\n     */\n    function _sendXDomainMessage(\n        address _canonicalTransactionChain,\n        bytes memory _message,\n        uint256 _gasLimit\n    ) internal {\n        ICanonicalTransactionChain(_canonicalTransactionChain).enqueue(\n            Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,\n            _gasLimit,\n            _message\n        );\n    }\n\n    /**\n     * Verifies that the given message is valid.\n     * @param _xDomainCalldata Calldata to verify.\n     * @param _proof Inclusion proof for the message.\n     * @return Whether or not the provided message is valid.\n     */\n    function _verifyXDomainMessageByChainId(\n        uint256 _chainId,\n        bytes memory _xDomainCalldata,\n        L2MessageInclusionProof memory _proof\n    ) internal view returns (bool) {\n        return (_verifyStateRootProofByChainId(_chainId, _proof) &&\n            _verifyStorageProof(_xDomainCalldata, _proof));\n    }\n\n    /**\n     * Verifies that the state root within an inclusion proof is valid.\n     * @param _proof Message inclusion proof.\n     * @return Whether or not the provided proof is valid.\n     */\n    function _verifyStateRootProofByChainId(uint256 _chainId, L2MessageInclusionProof memory _proof)\n        internal\n        view\n        returns (bool)\n    {\n        IStateCommitmentChain ovmStateCommitmentChain = IStateCommitmentChain(\n            resolve(\"StateCommitmentChain\")\n        );\n\n        return (!ovmStateCommitmentChain.insideFraudProofWindow(_proof.stateRootBatchHeader) &&\n            ovmStateCommitmentChain.verifyStateCommitmentByChainId(\n                _chainId,\n                _proof.stateRoot,\n                _proof.stateRootBatchHeader,\n                _proof.stateRootProof\n            ));\n    }\n\n    /**\n     * Sends a cross domain message via chain id.\n     * @param _chainId L2 chain id.\n     * @param _message Message to send.\n     * @param _gasLimit OVM gas limit for the message.\n     */\n    function _sendXDomainMessageViaChainId(\n        uint256 _chainId,\n        address _canonicalTransactionChain,\n        bytes memory _message,\n        uint256 _gasLimit\n    ) internal {\n        ICanonicalTransactionChain(_canonicalTransactionChain).enqueueByChainId(\n            _chainId,\n            Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,\n            _gasLimit,\n            _message\n        );\n    }\n}\n"
    },
    "contracts/standards/AddressAliasHelper.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.7;\n\nlibrary AddressAliasHelper {\n    uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n    /// @notice Utility function that converts the address in the L1 that submitted a tx to\n    /// the inbox to the msg.sender viewed in the L2\n    /// @param l1Address the address in the L1 that triggered the tx to L2\n    /// @return l2Address L2 address as viewed in msg.sender\n    function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n        unchecked {\n            l2Address = address(uint160(l1Address) + offset);\n        }\n    }\n\n    /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n    /// address in the L1 that submitted a tx to the inbox\n    /// @param l2Address L2 address as viewed in msg.sender\n    /// @return l1Address the address in the L1 that triggered the tx to L2\n    function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n        unchecked {\n            l1Address = address(uint160(l2Address) - offset);\n        }\n    }\n}\n"
    },
    "contracts/libraries/resolver/Lib_AddressResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_AddressManager } from \"./Lib_AddressManager.sol\";\n\n/**\n * @title Lib_AddressResolver\n */\nabstract contract Lib_AddressResolver {\n    /*************\n     * Variables *\n     *************/\n\n    Lib_AddressManager public libAddressManager;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Lib_AddressManager.\n     */\n    constructor(address _libAddressManager) {\n        libAddressManager = Lib_AddressManager(_libAddressManager);\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Resolves the address associated with a given name.\n     * @param _name Name to resolve an address for.\n     * @return Address associated with the given name.\n     */\n    function resolve(string memory _name) public view returns (address) {\n        return libAddressManager.getAddress(_name);\n    }\n}\n"
    },
    "contracts/libraries/resolver/Lib_AddressManager.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* External Imports */\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Lib_AddressManager\n */\ncontract Lib_AddressManager is Ownable {\n    /**********\n     * Events *\n     **********/\n\n    event AddressSet(string indexed _name, address _newAddress, address _oldAddress);\n\n    /*************\n     * Variables *\n     *************/\n\n    mapping(bytes32 => address) private addresses;\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Changes the address associated with a particular name.\n     * @param _name String name to associate an address with.\n     * @param _address Address to associate with the name.\n     */\n    function setAddress(string memory _name, address _address) external onlyOwner {\n        bytes32 nameHash = _getNameHash(_name);\n        address oldAddress = addresses[nameHash];\n        addresses[nameHash] = _address;\n\n        emit AddressSet(_name, _address, oldAddress);\n    }\n\n    /**\n     * Retrieves the address associated with a given name.\n     * @param _name Name to retrieve an address for.\n     * @return Address associated with the given name.\n     */\n    function getAddress(string memory _name) external view returns (address) {\n        return addresses[_getNameHash(_name)];\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Computes the hash of a name.\n     * @param _name Name to compute a hash for.\n     * @return Hash of the given name.\n     */\n    function _getNameHash(string memory _name) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(_name));\n    }\n}\n"
    },
    "contracts/libraries/trie/Lib_SecureMerkleTrie.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_MerkleTrie } from \"./Lib_MerkleTrie.sol\";\n\n/**\n * @title Lib_SecureMerkleTrie\n */\nlibrary Lib_SecureMerkleTrie {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * @notice Verifies a proof that a given key/value pair is present in the\n     * Merkle trie.\n     * @param _key Key of the node to search for, as a hex string.\n     * @param _value Value of the node to search for, as a hex string.\n     * @param _proof Merkle trie inclusion proof for the desired node. Unlike\n     * traditional Merkle trees, this proof is executed top-down and consists\n     * of a list of RLP-encoded nodes that make a path down to the target node.\n     * @param _root Known root of the Merkle trie. Used to verify that the\n     * included proof is correctly constructed.\n     * @return _verified `true` if the k/v pair exists in the trie, `false` otherwise.\n     */\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool _verified) {\n        bytes memory key = _getSecureKey(_key);\n        return Lib_MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n    }\n\n    /**\n     * @notice Updates a Merkle trie and returns a new root hash.\n     * @param _key Key of the node to update, as a hex string.\n     * @param _value Value of the node to update, as a hex string.\n     * @param _proof Merkle trie inclusion proof for the node *nearest* the\n     * target node. If the key exists, we can simply update the value.\n     * Otherwise, we need to modify the trie to handle the new k/v pair.\n     * @param _root Known root of the Merkle trie. Used to verify that the\n     * included proof is correctly constructed.\n     * @return _updatedRoot Root hash of the newly constructed trie.\n     */\n    function update(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bytes32 _updatedRoot) {\n        bytes memory key = _getSecureKey(_key);\n        return Lib_MerkleTrie.update(key, _value, _proof, _root);\n    }\n\n    /**\n     * @notice Retrieves the value associated with a given key.\n     * @param _key Key to search for, as hex bytes.\n     * @param _proof Merkle trie inclusion proof for the key.\n     * @param _root Known root of the Merkle trie.\n     * @return _exists Whether or not the key exists.\n     * @return _value Value of the key if it exists.\n     */\n    function get(\n        bytes memory _key,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool _exists, bytes memory _value) {\n        bytes memory key = _getSecureKey(_key);\n        return Lib_MerkleTrie.get(key, _proof, _root);\n    }\n\n    /**\n     * Computes the root hash for a trie with a single node.\n     * @param _key Key for the single node.\n     * @param _value Value for the single node.\n     * @return _updatedRoot Hash of the trie.\n     */\n    function getSingleNodeRootHash(bytes memory _key, bytes memory _value)\n        internal\n        pure\n        returns (bytes32 _updatedRoot)\n    {\n        bytes memory key = _getSecureKey(_key);\n        return Lib_MerkleTrie.getSingleNodeRootHash(key, _value);\n    }\n\n    /*********************\n     * Private Functions *\n     *********************/\n\n    /**\n     * Computes the secure counterpart to a key.\n     * @param _key Key to get a secure key from.\n     * @return _secureKey Secure version of the key.\n     */\n    function _getSecureKey(bytes memory _key) private pure returns (bytes memory _secureKey) {\n        return abi.encodePacked(keccak256(_key));\n    }\n}\n"
    },
    "contracts/libraries/constants/Lib_DefaultValues.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_DefaultValues\n */\nlibrary Lib_DefaultValues {\n    // The default x-domain message sender being set to a non-zero value makes\n    // deployment a bit more expensive, but in exchange the refund on every call to\n    // `relayMessage` by the L1 and L2 messengers will be higher.\n    address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\n}\n"
    },
    "contracts/libraries/constants/Lib_PredeployAddresses.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_PredeployAddresses\n */\nlibrary Lib_PredeployAddresses {\n    address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n    address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n    address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n    address internal constant MVM_CHAIN_CONFIG = 0x4200000000000000000000000000000000000005;\n    address internal constant OVM_ETH = 0x420000000000000000000000000000000000000A;\n    address internal constant MVM_COINBASE = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;\n    address internal constant L2_CROSS_DOMAIN_MESSENGER =\n        0x4200000000000000000000000000000000000007;\n    address internal constant LIB_ADDRESS_MANAGER = 0x4200000000000000000000000000000000000008;\n    address internal constant PROXY_EOA = 0x4200000000000000000000000000000000000009;\n    address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n    address payable internal constant SEQUENCER_FEE_WALLET =\n        payable(0x4200000000000000000000000000000000000011);\n    address internal constant L2_STANDARD_TOKEN_FACTORY =\n        0x4200000000000000000000000000000000000012;\n    address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n    address internal constant OVM_GASPRICE_ORACLE = 0x420000000000000000000000000000000000000F;\n}\n"
    },
    "contracts/libraries/bridge/Lib_CrossDomainUtils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_RLPReader } from \"../rlp/Lib_RLPReader.sol\";\n\n/**\n * @title Lib_CrossDomainUtils\n */\nlibrary Lib_CrossDomainUtils {\n    /**\n     * Generates the correct cross domain calldata for a message.\n     * @param _target Target contract address.\n     * @param _sender Message sender address.\n     * @param _message Message to send to the target.\n     * @param _messageNonce Nonce for the provided message.\n     * @return ABI encoded cross domain calldata.\n     */\n    function encodeXDomainCalldata(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce\n    ) internal pure returns (bytes memory) {\n        return\n            abi.encodeWithSignature(\n                \"relayMessage(address,address,bytes,uint256)\",\n                _target,\n                _sender,\n                _message,\n                _messageNonce\n            );\n    }\n\n    /**\n     * Generates the correct cross domain calldata for a message.\n     * @param _chainId L2 chain id.\n     * @param _target Target contract address.\n     * @param _sender Message sender address.\n     * @param _message Message to send to the target.\n     * @param _messageNonce Nonce for the provided message.\n     * @return ABI encoded cross domain calldata.\n     */\n    function encodeXDomainCalldataViaChainId(\n        uint256 _chainId,\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce\n    ) internal pure returns (bytes memory) {\n        return\n            abi.encodeWithSignature(\n                \"relayMessageViaChainId(uint256,address,address,bytes,uint256)\",\n                _chainId,\n                _target,\n                _sender,\n                _message,\n                _messageNonce\n            );\n    }\n}\n"
    },
    "contracts/L1/rollup/ICanonicalTransactionChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\n\n/* Interface Imports */\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title ICanonicalTransactionChain\n */\ninterface ICanonicalTransactionChain {\n    /**********\n     * Events *\n     **********/\n    event QueueGlobalMetadataSet(address _sender, uint256 _chainId, bytes27 _globalMetadata);\n\n    event QueuePushed(address _sender, uint256 _chainId, Lib_OVMCodec.QueueElement _object);\n\n    event QueueSetted(\n        address _sender,\n        uint256 _chainId,\n        uint256 _index,\n        Lib_OVMCodec.QueueElement _object\n    );\n\n    event QueueElementDeleted(\n        address _sender,\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    );\n\n    event BatchesGlobalMetadataSet(address _sender, uint256 _chainId, bytes27 _globalMetadata);\n\n    event BatchPushed(address _sender, uint256 _chainId, bytes32 _object, bytes27 _globalMetadata);\n\n    event BatchSetted(address _sender, uint256 _chainId, uint256 _index, bytes32 _object);\n\n    event BatchElementDeleted(\n        address _sender,\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    );\n\n    event L2GasParamsUpdated(\n        uint256 l2GasDiscountDivisor,\n        uint256 enqueueGasCost,\n        uint256 enqueueL2GasPrepaid\n    );\n\n    event TransactionEnqueued(\n        uint256 _chainId,\n        address indexed _l1TxOrigin,\n        address indexed _target,\n        uint256 _gasLimit,\n        bytes _data,\n        uint256 indexed _queueIndex,\n        uint256 _timestamp\n    );\n\n    event QueueBatchAppended(\n        uint256 _chainId,\n        uint256 _startingQueueIndex,\n        uint256 _numQueueElements,\n        uint256 _totalElements\n    );\n\n    event SequencerBatchAppended(\n        uint256 _chainId,\n        uint256 _startingQueueIndex,\n        uint256 _numQueueElements,\n        uint256 _totalElements\n    );\n\n    event TransactionBatchAppended(\n        uint256 _chainId,\n        uint256 indexed _batchIndex,\n        bytes32 _batchRoot,\n        uint256 _batchSize,\n        uint256 _prevTotalElements,\n        bytes _extraData\n    );\n\n    /***********\n     * Structs *\n     ***********/\n\n    struct BatchContext {\n        uint256 numSequencedTransactions;\n        uint256 numSubsequentQueueTransactions;\n        uint256 timestamp;\n        uint256 blockNumber;\n    }\n\n    /*******************************\n     * Authorized Setter Functions *\n     *******************************/\n\n    /**\n     * Allows the Burn Admin to update the parameters which determine the amount of gas to burn.\n     * The value of enqueueL2GasPrepaid is immediately updated as well.\n     */\n    function setGasParams(uint256 _l2GasDiscountDivisor, uint256 _enqueueGasCost) external;\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Accesses the batch storage container.\n     * @return Reference to the batch storage container.\n     */\n    function batches() external view returns (IChainStorageContainer);\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElements() external view returns (uint256 _totalElements);\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches);\n\n    /**\n     * Returns the index of the next element to be enqueued.\n     * @return Index for the next queue element.\n     */\n    function getNextQueueIndex() external view returns (uint40);\n\n    /**\n     * Gets the queue element at a particular index.\n     * @param _index Index of the queue element to access.\n     * @return _element Queue element at the given index.\n     */\n    function getQueueElement(uint256 _index)\n        external\n        view\n        returns (Lib_OVMCodec.QueueElement memory _element);\n\n    /**\n     * Returns the timestamp of the last transaction.\n     * @return Timestamp for the last transaction.\n     */\n    function getLastTimestamp() external view returns (uint40);\n\n    /**\n     * Returns the blocknumber of the last transaction.\n     * @return Blocknumber for the last transaction.\n     */\n    function getLastBlockNumber() external view returns (uint40);\n\n    /**\n     * Get the number of queue elements which have not yet been included.\n     * @return Number of pending queue elements.\n     */\n    function getNumPendingQueueElements() external view returns (uint40);\n\n    /**\n     * Retrieves the length of the queue, including\n     * both pending and canonical transactions.\n     * @return Length of the queue.\n     */\n    function getQueueLength() external view returns (uint40);\n\n    /**\n     * Adds a transaction to the queue.\n     * @param _target Target contract to send the transaction to.\n     * @param _gasLimit Gas limit for the given transaction.\n     * @param _data Transaction data.\n     */\n    function enqueue(\n        address _target,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) external;\n\n    /**\n     * Allows the sequencer to append a batch of transactions.\n     * @dev This function uses a custom encoding scheme for efficiency reasons.\n     * .param _shouldStartAtElement Specific batch we expect to start appending to.\n     * .param _totalElementsToAppend Total number of batch elements we expect to append.\n     * .param _contexts Array of batch contexts.\n     * .param _transactionDataFields Array of raw transaction data.\n     */\n    function appendSequencerBatch(\n        // uint40 _shouldStartAtElement,\n        // uint24 _totalElementsToAppend,\n        // BatchContext[] _contexts,\n        // bytes[] _transactionDataFields\n    ) external;\n\n    //added chain id function\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @param _chainId identity for the l2 chain.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _totalElements);\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @param _chainId identity for the l2 chain.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _totalBatches);\n\n    /**\n     * Returns the index of the next element to be enqueued.\n     * @param _chainId identity for the l2 chain.\n     * @return Index for the next queue element.\n     */\n    function getNextQueueIndexByChainId(uint256 _chainId) external view returns (uint40);\n\n    /**\n     * Gets the queue element at a particular index.\n     * @param _chainId identity for the l2 chain.\n     * @param _index Index of the queue element to access.\n     * @return _element Queue element at the given index.\n     */\n    function getQueueElementByChainId(uint256 _chainId, uint256 _index)\n        external\n        view\n        returns (Lib_OVMCodec.QueueElement memory _element);\n\n    /**\n     * Returns the timestamp of the last transaction.\n     * @param _chainId identity for the l2 chain.\n     * @return Timestamp for the last transaction.\n     */\n    function getLastTimestampByChainId(uint256 _chainId) external view returns (uint40);\n\n    /**\n     * Returns the blocknumber of the last transaction.\n     * @param _chainId identity for the l2 chain.\n     * @return Blocknumber for the last transaction.\n     */\n    function getLastBlockNumberByChainId(uint256 _chainId) external view returns (uint40);\n\n    /**\n     * Get the number of queue elements which have not yet been included.\n     * @param _chainId identity for the l2 chain.\n     * @return Number of pending queue elements.\n     */\n    function getNumPendingQueueElementsByChainId(uint256 _chainId) external view returns (uint40);\n\n    /**\n     * Retrieves the length of the queue, including\n     * both pending and canonical transactions.\n     * @param _chainId identity for the l2 chain.\n     * @return Length of the queue.\n     */\n    function getQueueLengthByChainId(uint256 _chainId) external view returns (uint40);\n\n    /**\n     * Adds a transaction to the queue.\n     * @param _chainId identity for the l2 chain.\n     * @param _target Target contract to send the transaction to.\n     * @param _gasLimit Gas limit for the given transaction.\n     * @param _data Transaction data.\n     */\n    function enqueueByChainId(\n        uint256 _chainId,\n        address _target,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) external;\n\n    /**\n     * Allows the sequencer to append a batch of transactions.\n     * @dev This function uses a custom encoding scheme for efficiency reasons.\n     * .param _chainId identity for the l2 chain.\n     * .param _shouldStartAtElement Specific batch we expect to start appending to.\n     * .param _totalElementsToAppend Total number of batch elements we expect to append.\n     * .param _contexts Array of batch contexts.\n     * .param _transactionDataFields Array of raw transaction data.\n     */\n    function appendSequencerBatchByChainId(\n        // uint256 _chainId,\n        // uint40 _shouldStartAtElement,\n        // uint24 _totalElementsToAppend,\n        // BatchContext[] _contexts,\n        // bytes[] _transactionDataFields\n    ) external;\n\n    function pushQueueByChainId(uint256 _chainId, Lib_OVMCodec.QueueElement calldata _object)\n        external;\n\n    function setQueueByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        Lib_OVMCodec.QueueElement calldata _object\n    ) external;\n\n    function setBatchGlobalMetadataByChainId(uint256 _chainId, bytes27 _globalMetadata) external;\n\n    function getBatchGlobalMetadataByChainId(uint256 _chainId) external view returns (bytes27);\n\n    function lengthBatchByChainId(uint256 _chainId) external view returns (uint256);\n\n    function pushBatchByChainId(\n        uint256 _chainId,\n        bytes32 _object,\n        bytes27 _globalMetadata\n    ) external;\n\n    function setBatchByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes32 _object\n    ) external;\n\n    function getBatchByChainId(uint256 _chainId, uint256 _index) external view returns (bytes32);\n\n    function deleteBatchElementsAfterInclusiveByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    ) external;\n}\n"
    },
    "contracts/L1/rollup/IStateCommitmentChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title IStateCommitmentChain\n */\ninterface IStateCommitmentChain {\n    /**********\n     * Events *\n     **********/\n\n    event StateBatchAppended(\n        uint256 _chainId,\n        uint256 indexed _batchIndex,\n        bytes32 _batchRoot,\n        uint256 _batchSize,\n        uint256 _prevTotalElements,\n        bytes _extraData\n    );\n\n    event StateBatchDeleted(uint256 _chainId, uint256 indexed _batchIndex, bytes32 _batchRoot);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function batches() external view returns (IChainStorageContainer);\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElements() external view returns (uint256 _totalElements);\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches);\n\n    /**\n     * Retrieves the timestamp of the last batch submitted by the sequencer.\n     * @return _lastSequencerTimestamp Last sequencer batch timestamp.\n     */\n    function getLastSequencerTimestamp() external view returns (uint256 _lastSequencerTimestamp);\n\n    /**\n     * Appends a batch of state roots to the chain.\n     * @param _batch Batch of state roots.\n     * @param _shouldStartAtElement Index of the element at which this batch should start.\n     */\n    function appendStateBatch(bytes32[] calldata _batch, uint256 _shouldStartAtElement) external;\n\n    /**\n     * Deletes all state roots after (and including) a given batch.\n     * @param _batchHeader Header of the batch to start deleting from.\n     */\n    function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external;\n\n    /**\n     * Verifies a batch inclusion proof.\n     * @param _element Hash of the element to verify a proof for.\n     * @param _batchHeader Header of the batch in which the element was included.\n     * @param _proof Merkle inclusion proof for the element.\n     */\n    function verifyStateCommitment(\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) external view returns (bool _verified);\n\n    /**\n     * Checks whether a given batch is still inside its fraud proof window.\n     * @param _batchHeader Header of the batch to check.\n     * @return _inside Whether or not the batch is inside the fraud proof window.\n     */\n    function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)\n        external\n        view\n        returns (bool _inside);\n\n    /********************\n     * chain id added func *\n     ********************/\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @param _chainId identity for the l2 chain.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _totalElements);\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @param _chainId identity for the l2 chain.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _totalBatches);\n\n    /**\n     * Retrieves the timestamp of the last batch submitted by the sequencer.\n     * @param _chainId identity for the l2 chain.\n     * @return _lastSequencerTimestamp Last sequencer batch timestamp.\n     */\n    function getLastSequencerTimestampByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _lastSequencerTimestamp);\n\n    /**\n     * Appends a batch of state roots to the chain.\n     * @param _chainId identity for the l2 chain.\n     * @param _batch Batch of state roots.\n     * @param _shouldStartAtElement Index of the element at which this batch should start.\n     */\n    function appendStateBatchByChainId(\n        uint256 _chainId,\n        bytes32[] calldata _batch,\n        uint256 _shouldStartAtElement,\n        string calldata proposer\n    ) external;\n\n    /**\n     * Deletes all state roots after (and including) a given batch.\n     * @param _chainId identity for the l2 chain.\n     * @param _batchHeader Header of the batch to start deleting from.\n     */\n    function deleteStateBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) external;\n\n    /**\n     * Verifies a batch inclusion proof.\n     * @param _chainId identity for the l2 chain.\n     * @param _element Hash of the element to verify a proof for.\n     * @param _batchHeader Header of the batch in which the element was included.\n     * @param _proof Merkle inclusion proof for the element.\n     */\n    function verifyStateCommitmentByChainId(\n        uint256 _chainId,\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) external view returns (bool _verified);\n\n    /**\n     * Checks whether a given batch is still inside its fraud proof window.\n     * @param _chainId identity for the l2 chain.\n     * @param _batchHeader Header of the batch to check.\n     * @return _inside Whether or not the batch is inside the fraud proof window.\n     */\n    function insideFraudProofWindowByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) external view returns (bool _inside);\n}\n"
    },
    "contracts/MVM/iMVM_DiscountOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface iMVM_DiscountOracle {\n    function setDiscount(uint256 _discount) external;\n\n    function setMinL2Gas(uint256 _minL2Gas) external;\n\n    function setWhitelistedXDomainSender(address _sender, bool _isWhitelisted) external;\n\n    function isXDomainSenderAllowed(address _sender) external view returns (bool);\n\n    function setAllowAllXDomainSenders(bool _allowAllXDomainSenders) external;\n\n    function getMinL2Gas() external view returns (uint256);\n\n    function getDiscount() external view returns (uint256);\n\n    function processL2SeqGas(address sender, uint256 _chainId) external payable;\n\n    function withdrawToSeq(uint256 _amount, uint256 _chainId) external;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal initializer {\n        __Context_init_unchained();\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal initializer {\n        _setOwner(_msgSender());\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _setOwner(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _setOwner(newOwner);\n    }\n\n    function _setOwner(address newOwner) private {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n    uint256[49] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    function __Pausable_init() internal initializer {\n        __Context_init_unchained();\n        __Pausable_init_unchained();\n    }\n\n    function __Pausable_init_unchained() internal initializer {\n        _paused = false;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        require(!paused(), \"Pausable: paused\");\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        require(paused(), \"Pausable: not paused\");\n        _;\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n    uint256[49] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal initializer {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal initializer {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and make it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        // On the first call to nonReentrant, _notEntered will be true\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n\n        _;\n\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n    uint256[49] private __gap;\n}\n"
    },
    "@openzeppelin/contracts/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _setOwner(_msgSender());\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _setOwner(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _setOwner(newOwner);\n    }\n\n    function _setOwner(address newOwner) private {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
    },
    "contracts/libraries/trie/Lib_MerkleTrie.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_BytesUtils } from \"../utils/Lib_BytesUtils.sol\";\nimport { Lib_RLPReader } from \"../rlp/Lib_RLPReader.sol\";\nimport { Lib_RLPWriter } from \"../rlp/Lib_RLPWriter.sol\";\n\n/**\n * @title Lib_MerkleTrie\n */\nlibrary Lib_MerkleTrie {\n    /*******************\n     * Data Structures *\n     *******************/\n\n    enum NodeType {\n        BranchNode,\n        ExtensionNode,\n        LeafNode\n    }\n\n    struct TrieNode {\n        bytes encoded;\n        Lib_RLPReader.RLPItem[] decoded;\n    }\n\n    /**********************\n     * Contract Constants *\n     **********************/\n\n    // TREE_RADIX determines the number of elements per branch node.\n    uint256 constant TREE_RADIX = 16;\n    // Branch nodes have TREE_RADIX elements plus an additional `value` slot.\n    uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n    // Leaf nodes and extension nodes always have two elements, a `path` and a `value`.\n    uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n    // Prefixes are prepended to the `path` within a leaf or extension node and\n    // allow us to differentiate between the two node types. `ODD` or `EVEN` is\n    // determined by the number of nibbles within the unprefixed `path`. If the\n    // number of nibbles if even, we need to insert an extra padding nibble so\n    // the resulting prefixed `path` has an even number of nibbles.\n    uint8 constant PREFIX_EXTENSION_EVEN = 0;\n    uint8 constant PREFIX_EXTENSION_ODD = 1;\n    uint8 constant PREFIX_LEAF_EVEN = 2;\n    uint8 constant PREFIX_LEAF_ODD = 3;\n\n    // Just a utility constant. RLP represents `NULL` as 0x80.\n    bytes1 constant RLP_NULL = bytes1(0x80);\n    bytes constant RLP_NULL_BYTES = hex\"80\";\n    bytes32 internal constant KECCAK256_RLP_NULL_BYTES = keccak256(RLP_NULL_BYTES);\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * @notice Verifies a proof that a given key/value pair is present in the\n     * Merkle trie.\n     * @param _key Key of the node to search for, as a hex string.\n     * @param _value Value of the node to search for, as a hex string.\n     * @param _proof Merkle trie inclusion proof for the desired node. Unlike\n     * traditional Merkle trees, this proof is executed top-down and consists\n     * of a list of RLP-encoded nodes that make a path down to the target node.\n     * @param _root Known root of the Merkle trie. Used to verify that the\n     * included proof is correctly constructed.\n     * @return _verified `true` if the k/v pair exists in the trie, `false` otherwise.\n     */\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool _verified) {\n        (bool exists, bytes memory value) = get(_key, _proof, _root);\n\n        return (exists && Lib_BytesUtils.equal(_value, value));\n    }\n\n    /**\n     * @notice Updates a Merkle trie and returns a new root hash.\n     * @param _key Key of the node to update, as a hex string.\n     * @param _value Value of the node to update, as a hex string.\n     * @param _proof Merkle trie inclusion proof for the node *nearest* the\n     * target node. If the key exists, we can simply update the value.\n     * Otherwise, we need to modify the trie to handle the new k/v pair.\n     * @param _root Known root of the Merkle trie. Used to verify that the\n     * included proof is correctly constructed.\n     * @return _updatedRoot Root hash of the newly constructed trie.\n     */\n    function update(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bytes32 _updatedRoot) {\n        // Special case when inserting the very first node.\n        if (_root == KECCAK256_RLP_NULL_BYTES) {\n            return getSingleNodeRootHash(_key, _value);\n        }\n\n        TrieNode[] memory proof = _parseProof(_proof);\n        (uint256 pathLength, bytes memory keyRemainder, ) = _walkNodePath(proof, _key, _root);\n        TrieNode[] memory newPath = _getNewPath(proof, pathLength, _key, keyRemainder, _value);\n\n        return _getUpdatedTrieRoot(newPath, _key);\n    }\n\n    /**\n     * @notice Retrieves the value associated with a given key.\n     * @param _key Key to search for, as hex bytes.\n     * @param _proof Merkle trie inclusion proof for the key.\n     * @param _root Known root of the Merkle trie.\n     * @return _exists Whether or not the key exists.\n     * @return _value Value of the key if it exists.\n     */\n    function get(\n        bytes memory _key,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool _exists, bytes memory _value) {\n        TrieNode[] memory proof = _parseProof(_proof);\n        (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(\n            proof,\n            _key,\n            _root\n        );\n\n        bool exists = keyRemainder.length == 0;\n\n        require(exists || isFinalNode, \"Provided proof is invalid.\");\n\n        bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes(\"\");\n\n        return (exists, value);\n    }\n\n    /**\n     * Computes the root hash for a trie with a single node.\n     * @param _key Key for the single node.\n     * @param _value Value for the single node.\n     * @return _updatedRoot Hash of the trie.\n     */\n    function getSingleNodeRootHash(bytes memory _key, bytes memory _value)\n        internal\n        pure\n        returns (bytes32 _updatedRoot)\n    {\n        return keccak256(_makeLeafNode(Lib_BytesUtils.toNibbles(_key), _value).encoded);\n    }\n\n    /*********************\n     * Private Functions *\n     *********************/\n\n    /**\n     * @notice Walks through a proof using a provided key.\n     * @param _proof Inclusion proof to walk through.\n     * @param _key Key to use for the walk.\n     * @param _root Known root of the trie.\n     * @return _pathLength Length of the final path\n     * @return _keyRemainder Portion of the key remaining after the walk.\n     * @return _isFinalNode Whether or not we've hit a dead end.\n     */\n    function _walkNodePath(\n        TrieNode[] memory _proof,\n        bytes memory _key,\n        bytes32 _root\n    )\n        private\n        pure\n        returns (\n            uint256 _pathLength,\n            bytes memory _keyRemainder,\n            bool _isFinalNode\n        )\n    {\n        uint256 pathLength = 0;\n        bytes memory key = Lib_BytesUtils.toNibbles(_key);\n\n        bytes32 currentNodeID = _root;\n        uint256 currentKeyIndex = 0;\n        uint256 currentKeyIncrement = 0;\n        TrieNode memory currentNode;\n\n        // Proof is top-down, so we start at the first element (root).\n        for (uint256 i = 0; i < _proof.length; i++) {\n            currentNode = _proof[i];\n            currentKeyIndex += currentKeyIncrement;\n\n            // Keep track of the proof elements we actually need.\n            // It's expensive to resize arrays, so this simply reduces gas costs.\n            pathLength += 1;\n\n            if (currentKeyIndex == 0) {\n                // First proof element is always the root node.\n                require(keccak256(currentNode.encoded) == currentNodeID, \"Invalid root hash\");\n            } else if (currentNode.encoded.length >= 32) {\n                // Nodes 32 bytes or larger are hashed inside branch nodes.\n                require(\n                    keccak256(currentNode.encoded) == currentNodeID,\n                    \"Invalid large internal hash\"\n                );\n            } else {\n                // Nodes smaller than 31 bytes aren't hashed.\n                require(\n                    Lib_BytesUtils.toBytes32(currentNode.encoded) == currentNodeID,\n                    \"Invalid internal node hash\"\n                );\n            }\n\n            if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n                if (currentKeyIndex == key.length) {\n                    // We've hit the end of the key\n                    // meaning the value should be within this branch node.\n                    break;\n                } else {\n                    // We're not at the end of the key yet.\n                    // Figure out what the next node ID should be and continue.\n                    uint8 branchKey = uint8(key[currentKeyIndex]);\n                    Lib_RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n                    currentNodeID = _getNodeID(nextNode);\n                    currentKeyIncrement = 1;\n                    continue;\n                }\n            } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n                bytes memory path = _getNodePath(currentNode);\n                uint8 prefix = uint8(path[0]);\n                uint8 offset = 2 - (prefix % 2);\n                bytes memory pathRemainder = Lib_BytesUtils.slice(path, offset);\n                bytes memory keyRemainder = Lib_BytesUtils.slice(key, currentKeyIndex);\n                uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n                if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n                    if (\n                        pathRemainder.length == sharedNibbleLength &&\n                        keyRemainder.length == sharedNibbleLength\n                    ) {\n                        // The key within this leaf matches our key exactly.\n                        // Increment the key index to reflect that we have no remainder.\n                        currentKeyIndex += sharedNibbleLength;\n                    }\n\n                    // We've hit a leaf node, so our next node should be NULL.\n                    currentNodeID = bytes32(RLP_NULL);\n                    break;\n                } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n                    if (sharedNibbleLength != pathRemainder.length) {\n                        // Our extension node is not identical to the remainder.\n                        // We've hit the end of this path\n                        // updates will need to modify this extension.\n                        currentNodeID = bytes32(RLP_NULL);\n                        break;\n                    } else {\n                        // Our extension shares some nibbles.\n                        // Carry on to the next node.\n                        currentNodeID = _getNodeID(currentNode.decoded[1]);\n                        currentKeyIncrement = sharedNibbleLength;\n                        continue;\n                    }\n                } else {\n                    revert(\"Received a node with an unknown prefix\");\n                }\n            } else {\n                revert(\"Received an unparseable node.\");\n            }\n        }\n\n        // If our node ID is NULL, then we're at a dead end.\n        bool isFinalNode = currentNodeID == bytes32(RLP_NULL);\n        return (pathLength, Lib_BytesUtils.slice(key, currentKeyIndex), isFinalNode);\n    }\n\n    /**\n     * @notice Creates new nodes to support a k/v pair insertion into a given Merkle trie path.\n     * @param _path Path to the node nearest the k/v pair.\n     * @param _pathLength Length of the path. Necessary because the provided path may include\n     *  additional nodes (e.g., it comes directly from a proof) and we can't resize in-memory\n     *  arrays without costly duplication.\n     * @param _key Full original key.\n     * @param _keyRemainder Portion of the initial key that must be inserted into the trie.\n     * @param _value Value to insert at the given key.\n     * @return _newPath A new path with the inserted k/v pair and extra supporting nodes.\n     */\n    function _getNewPath(\n        TrieNode[] memory _path,\n        uint256 _pathLength,\n        bytes memory _key,\n        bytes memory _keyRemainder,\n        bytes memory _value\n    ) private pure returns (TrieNode[] memory _newPath) {\n        bytes memory keyRemainder = _keyRemainder;\n\n        // Most of our logic depends on the status of the last node in the path.\n        TrieNode memory lastNode = _path[_pathLength - 1];\n        NodeType lastNodeType = _getNodeType(lastNode);\n\n        // Create an array for newly created nodes.\n        // We need up to three new nodes, depending on the contents of the last node.\n        // Since array resizing is expensive, we'll keep track of the size manually.\n        // We're using an explicit `totalNewNodes += 1` after insertions for clarity.\n        TrieNode[] memory newNodes = new TrieNode[](3);\n        uint256 totalNewNodes = 0;\n\n        // solhint-disable-next-line max-line-length\n        // Reference: https://github.com/ethereumjs/merkle-patricia-tree/blob/c0a10395aab37d42c175a47114ebfcbd7efcf059/src/baseTrie.ts#L294-L313\n        bool matchLeaf = false;\n        if (lastNodeType == NodeType.LeafNode) {\n            uint256 l = 0;\n            if (_path.length > 0) {\n                for (uint256 i = 0; i < _path.length - 1; i++) {\n                    if (_getNodeType(_path[i]) == NodeType.BranchNode) {\n                        l++;\n                    } else {\n                        l += _getNodeKey(_path[i]).length;\n                    }\n                }\n            }\n\n            if (\n                _getSharedNibbleLength(\n                    _getNodeKey(lastNode),\n                    Lib_BytesUtils.slice(Lib_BytesUtils.toNibbles(_key), l)\n                ) ==\n                _getNodeKey(lastNode).length &&\n                keyRemainder.length == 0\n            ) {\n                matchLeaf = true;\n            }\n        }\n\n        if (matchLeaf) {\n            // We've found a leaf node with the given key.\n            // Simply need to update the value of the node to match.\n            newNodes[totalNewNodes] = _makeLeafNode(_getNodeKey(lastNode), _value);\n            totalNewNodes += 1;\n        } else if (lastNodeType == NodeType.BranchNode) {\n            if (keyRemainder.length == 0) {\n                // We've found a branch node with the given key.\n                // Simply need to update the value of the node to match.\n                newNodes[totalNewNodes] = _editBranchValue(lastNode, _value);\n                totalNewNodes += 1;\n            } else {\n                // We've found a branch node, but it doesn't contain our key.\n                // Reinsert the old branch for now.\n                newNodes[totalNewNodes] = lastNode;\n                totalNewNodes += 1;\n                // Create a new leaf node, slicing our remainder since the first byte points\n                // to our branch node.\n                newNodes[totalNewNodes] = _makeLeafNode(\n                    Lib_BytesUtils.slice(keyRemainder, 1),\n                    _value\n                );\n                totalNewNodes += 1;\n            }\n        } else {\n            // Our last node is either an extension node or a leaf node with a different key.\n            bytes memory lastNodeKey = _getNodeKey(lastNode);\n            uint256 sharedNibbleLength = _getSharedNibbleLength(lastNodeKey, keyRemainder);\n\n            if (sharedNibbleLength != 0) {\n                // We've got some shared nibbles between the last node and our key remainder.\n                // We'll need to insert an extension node that covers these shared nibbles.\n                bytes memory nextNodeKey = Lib_BytesUtils.slice(lastNodeKey, 0, sharedNibbleLength);\n                newNodes[totalNewNodes] = _makeExtensionNode(nextNodeKey, _getNodeHash(_value));\n                totalNewNodes += 1;\n\n                // Cut down the keys since we've just covered these shared nibbles.\n                lastNodeKey = Lib_BytesUtils.slice(lastNodeKey, sharedNibbleLength);\n                keyRemainder = Lib_BytesUtils.slice(keyRemainder, sharedNibbleLength);\n            }\n\n            // Create an empty branch to fill in.\n            TrieNode memory newBranch = _makeEmptyBranchNode();\n\n            if (lastNodeKey.length == 0) {\n                // Key remainder was larger than the key for our last node.\n                // The value within our last node is therefore going to be shifted into\n                // a branch value slot.\n                newBranch = _editBranchValue(newBranch, _getNodeValue(lastNode));\n            } else {\n                // Last node key was larger than the key remainder.\n                // We're going to modify some index of our branch.\n                uint8 branchKey = uint8(lastNodeKey[0]);\n                // Move on to the next nibble.\n                lastNodeKey = Lib_BytesUtils.slice(lastNodeKey, 1);\n\n                if (lastNodeType == NodeType.LeafNode) {\n                    // We're dealing with a leaf node.\n                    // We'll modify the key and insert the old leaf node into the branch index.\n                    TrieNode memory modifiedLastNode = _makeLeafNode(\n                        lastNodeKey,\n                        _getNodeValue(lastNode)\n                    );\n                    newBranch = _editBranchIndex(\n                        newBranch,\n                        branchKey,\n                        _getNodeHash(modifiedLastNode.encoded)\n                    );\n                } else if (lastNodeKey.length != 0) {\n                    // We're dealing with a shrinking extension node.\n                    // We need to modify the node to decrease the size of the key.\n                    TrieNode memory modifiedLastNode = _makeExtensionNode(\n                        lastNodeKey,\n                        _getNodeValue(lastNode)\n                    );\n                    newBranch = _editBranchIndex(\n                        newBranch,\n                        branchKey,\n                        _getNodeHash(modifiedLastNode.encoded)\n                    );\n                } else {\n                    // We're dealing with an unnecessary extension node.\n                    // We're going to delete the node entirely.\n                    // Simply insert its current value into the branch index.\n                    newBranch = _editBranchIndex(newBranch, branchKey, _getNodeValue(lastNode));\n                }\n            }\n\n            if (keyRemainder.length == 0) {\n                // We've got nothing left in the key remainder.\n                // Simply insert the value into the branch value slot.\n                newBranch = _editBranchValue(newBranch, _value);\n                // Push the branch into the list of new nodes.\n                newNodes[totalNewNodes] = newBranch;\n                totalNewNodes += 1;\n            } else {\n                // We've got some key remainder to work with.\n                // We'll be inserting a leaf node into the trie.\n                // First, move on to the next nibble.\n                keyRemainder = Lib_BytesUtils.slice(keyRemainder, 1);\n                // Push the branch into the list of new nodes.\n                newNodes[totalNewNodes] = newBranch;\n                totalNewNodes += 1;\n                // Push a new leaf node for our k/v pair.\n                newNodes[totalNewNodes] = _makeLeafNode(keyRemainder, _value);\n                totalNewNodes += 1;\n            }\n        }\n\n        // Finally, join the old path with our newly created nodes.\n        // Since we're overwriting the last node in the path, we use `_pathLength - 1`.\n        return _joinNodeArrays(_path, _pathLength - 1, newNodes, totalNewNodes);\n    }\n\n    /**\n     * @notice Computes the trie root from a given path.\n     * @param _nodes Path to some k/v pair.\n     * @param _key Key for the k/v pair.\n     * @return _updatedRoot Root hash for the updated trie.\n     */\n    function _getUpdatedTrieRoot(TrieNode[] memory _nodes, bytes memory _key)\n        private\n        pure\n        returns (bytes32 _updatedRoot)\n    {\n        bytes memory key = Lib_BytesUtils.toNibbles(_key);\n\n        // Some variables to keep track of during iteration.\n        TrieNode memory currentNode;\n        NodeType currentNodeType;\n        bytes memory previousNodeHash;\n\n        // Run through the path backwards to rebuild our root hash.\n        for (uint256 i = _nodes.length; i > 0; i--) {\n            // Pick out the current node.\n            currentNode = _nodes[i - 1];\n            currentNodeType = _getNodeType(currentNode);\n\n            if (currentNodeType == NodeType.LeafNode) {\n                // Leaf nodes are already correctly encoded.\n                // Shift the key over to account for the nodes key.\n                bytes memory nodeKey = _getNodeKey(currentNode);\n                key = Lib_BytesUtils.slice(key, 0, key.length - nodeKey.length);\n            } else if (currentNodeType == NodeType.ExtensionNode) {\n                // Shift the key over to account for the nodes key.\n                bytes memory nodeKey = _getNodeKey(currentNode);\n                key = Lib_BytesUtils.slice(key, 0, key.length - nodeKey.length);\n\n                // If this node is the last element in the path, it'll be correctly encoded\n                // and we can skip this part.\n                if (previousNodeHash.length > 0) {\n                    // Re-encode the node based on the previous node.\n                    currentNode = _editExtensionNodeValue(currentNode, previousNodeHash);\n                }\n            } else if (currentNodeType == NodeType.BranchNode) {\n                // If this node is the last element in the path, it'll be correctly encoded\n                // and we can skip this part.\n                if (previousNodeHash.length > 0) {\n                    // Re-encode the node based on the previous node.\n                    uint8 branchKey = uint8(key[key.length - 1]);\n                    key = Lib_BytesUtils.slice(key, 0, key.length - 1);\n                    currentNode = _editBranchIndex(currentNode, branchKey, previousNodeHash);\n                }\n            }\n\n            // Compute the node hash for the next iteration.\n            previousNodeHash = _getNodeHash(currentNode.encoded);\n        }\n\n        // Current node should be the root at this point.\n        // Simply return the hash of its encoding.\n        return keccak256(currentNode.encoded);\n    }\n\n    /**\n     * @notice Parses an RLP-encoded proof into something more useful.\n     * @param _proof RLP-encoded proof to parse.\n     * @return _parsed Proof parsed into easily accessible structs.\n     */\n    function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory _parsed) {\n        Lib_RLPReader.RLPItem[] memory nodes = Lib_RLPReader.readList(_proof);\n        TrieNode[] memory proof = new TrieNode[](nodes.length);\n\n        for (uint256 i = 0; i < nodes.length; i++) {\n            bytes memory encoded = Lib_RLPReader.readBytes(nodes[i]);\n            proof[i] = TrieNode({ encoded: encoded, decoded: Lib_RLPReader.readList(encoded) });\n        }\n\n        return proof;\n    }\n\n    /**\n     * @notice Picks out the ID for a node. Node ID is referred to as the\n     * \"hash\" within the specification, but nodes < 32 bytes are not actually\n     * hashed.\n     * @param _node Node to pull an ID for.\n     * @return _nodeID ID for the node, depending on the size of its contents.\n     */\n    function _getNodeID(Lib_RLPReader.RLPItem memory _node) private pure returns (bytes32 _nodeID) {\n        bytes memory nodeID;\n\n        if (_node.length < 32) {\n            // Nodes smaller than 32 bytes are RLP encoded.\n            nodeID = Lib_RLPReader.readRawBytes(_node);\n        } else {\n            // Nodes 32 bytes or larger are hashed.\n            nodeID = Lib_RLPReader.readBytes(_node);\n        }\n\n        return Lib_BytesUtils.toBytes32(nodeID);\n    }\n\n    /**\n     * @notice Gets the path for a leaf or extension node.\n     * @param _node Node to get a path for.\n     * @return _path Node path, converted to an array of nibbles.\n     */\n    function _getNodePath(TrieNode memory _node) private pure returns (bytes memory _path) {\n        return Lib_BytesUtils.toNibbles(Lib_RLPReader.readBytes(_node.decoded[0]));\n    }\n\n    /**\n     * @notice Gets the key for a leaf or extension node. Keys are essentially\n     * just paths without any prefix.\n     * @param _node Node to get a key for.\n     * @return _key Node key, converted to an array of nibbles.\n     */\n    function _getNodeKey(TrieNode memory _node) private pure returns (bytes memory _key) {\n        return _removeHexPrefix(_getNodePath(_node));\n    }\n\n    /**\n     * @notice Gets the path for a node.\n     * @param _node Node to get a value for.\n     * @return _value Node value, as hex bytes.\n     */\n    function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory _value) {\n        return Lib_RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]);\n    }\n\n    /**\n     * @notice Computes the node hash for an encoded node. Nodes < 32 bytes\n     * are not hashed, all others are keccak256 hashed.\n     * @param _encoded Encoded node to hash.\n     * @return _hash Hash of the encoded node. Simply the input if < 32 bytes.\n     */\n    function _getNodeHash(bytes memory _encoded) private pure returns (bytes memory _hash) {\n        if (_encoded.length < 32) {\n            return _encoded;\n        } else {\n            return abi.encodePacked(keccak256(_encoded));\n        }\n    }\n\n    /**\n     * @notice Determines the type for a given node.\n     * @param _node Node to determine a type for.\n     * @return _type Type of the node; BranchNode/ExtensionNode/LeafNode.\n     */\n    function _getNodeType(TrieNode memory _node) private pure returns (NodeType _type) {\n        if (_node.decoded.length == BRANCH_NODE_LENGTH) {\n            return NodeType.BranchNode;\n        } else if (_node.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n            bytes memory path = _getNodePath(_node);\n            uint8 prefix = uint8(path[0]);\n\n            if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n                return NodeType.LeafNode;\n            } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n                return NodeType.ExtensionNode;\n            }\n        }\n\n        revert(\"Invalid node type\");\n    }\n\n    /**\n     * @notice Utility; determines the number of nibbles shared between two\n     * nibble arrays.\n     * @param _a First nibble array.\n     * @param _b Second nibble array.\n     * @return _shared Number of shared nibbles.\n     */\n    function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n        private\n        pure\n        returns (uint256 _shared)\n    {\n        uint256 i = 0;\n        while (_a.length > i && _b.length > i && _a[i] == _b[i]) {\n            i++;\n        }\n        return i;\n    }\n\n    /**\n     * @notice Utility; converts an RLP-encoded node into our nice struct.\n     * @param _raw RLP-encoded node to convert.\n     * @return _node Node as a TrieNode struct.\n     */\n    function _makeNode(bytes[] memory _raw) private pure returns (TrieNode memory _node) {\n        bytes memory encoded = Lib_RLPWriter.writeList(_raw);\n\n        return TrieNode({ encoded: encoded, decoded: Lib_RLPReader.readList(encoded) });\n    }\n\n    /**\n     * @notice Utility; converts an RLP-decoded node into our nice struct.\n     * @param _items RLP-decoded node to convert.\n     * @return _node Node as a TrieNode struct.\n     */\n    function _makeNode(Lib_RLPReader.RLPItem[] memory _items)\n        private\n        pure\n        returns (TrieNode memory _node)\n    {\n        bytes[] memory raw = new bytes[](_items.length);\n        for (uint256 i = 0; i < _items.length; i++) {\n            raw[i] = Lib_RLPReader.readRawBytes(_items[i]);\n        }\n        return _makeNode(raw);\n    }\n\n    /**\n     * @notice Creates a new extension node.\n     * @param _key Key for the extension node, unprefixed.\n     * @param _value Value for the extension node.\n     * @return _node New extension node with the given k/v pair.\n     */\n    function _makeExtensionNode(bytes memory _key, bytes memory _value)\n        private\n        pure\n        returns (TrieNode memory _node)\n    {\n        bytes[] memory raw = new bytes[](2);\n        bytes memory key = _addHexPrefix(_key, false);\n        raw[0] = Lib_RLPWriter.writeBytes(Lib_BytesUtils.fromNibbles(key));\n        raw[1] = Lib_RLPWriter.writeBytes(_value);\n        return _makeNode(raw);\n    }\n\n    /**\n     * Creates a new extension node with the same key but a different value.\n     * @param _node Extension node to copy and modify.\n     * @param _value New value for the extension node.\n     * @return New node with the same key and different value.\n     */\n    function _editExtensionNodeValue(TrieNode memory _node, bytes memory _value)\n        private\n        pure\n        returns (TrieNode memory)\n    {\n        bytes[] memory raw = new bytes[](2);\n        bytes memory key = _addHexPrefix(_getNodeKey(_node), false);\n        raw[0] = Lib_RLPWriter.writeBytes(Lib_BytesUtils.fromNibbles(key));\n        if (_value.length < 32) {\n            raw[1] = _value;\n        } else {\n            raw[1] = Lib_RLPWriter.writeBytes(_value);\n        }\n        return _makeNode(raw);\n    }\n\n    /**\n     * @notice Creates a new leaf node.\n     * @dev This function is essentially identical to `_makeExtensionNode`.\n     * Although we could route both to a single method with a flag, it's\n     * more gas efficient to keep them separate and duplicate the logic.\n     * @param _key Key for the leaf node, unprefixed.\n     * @param _value Value for the leaf node.\n     * @return _node New leaf node with the given k/v pair.\n     */\n    function _makeLeafNode(bytes memory _key, bytes memory _value)\n        private\n        pure\n        returns (TrieNode memory _node)\n    {\n        bytes[] memory raw = new bytes[](2);\n        bytes memory key = _addHexPrefix(_key, true);\n        raw[0] = Lib_RLPWriter.writeBytes(Lib_BytesUtils.fromNibbles(key));\n        raw[1] = Lib_RLPWriter.writeBytes(_value);\n        return _makeNode(raw);\n    }\n\n    /**\n     * @notice Creates an empty branch node.\n     * @return _node Empty branch node as a TrieNode struct.\n     */\n    function _makeEmptyBranchNode() private pure returns (TrieNode memory _node) {\n        bytes[] memory raw = new bytes[](BRANCH_NODE_LENGTH);\n        for (uint256 i = 0; i < raw.length; i++) {\n            raw[i] = RLP_NULL_BYTES;\n        }\n        return _makeNode(raw);\n    }\n\n    /**\n     * @notice Modifies the value slot for a given branch.\n     * @param _branch Branch node to modify.\n     * @param _value Value to insert into the branch.\n     * @return _updatedNode Modified branch node.\n     */\n    function _editBranchValue(TrieNode memory _branch, bytes memory _value)\n        private\n        pure\n        returns (TrieNode memory _updatedNode)\n    {\n        bytes memory encoded = Lib_RLPWriter.writeBytes(_value);\n        _branch.decoded[_branch.decoded.length - 1] = Lib_RLPReader.toRLPItem(encoded);\n        return _makeNode(_branch.decoded);\n    }\n\n    /**\n     * @notice Modifies a slot at an index for a given branch.\n     * @param _branch Branch node to modify.\n     * @param _index Slot index to modify.\n     * @param _value Value to insert into the slot.\n     * @return _updatedNode Modified branch node.\n     */\n    function _editBranchIndex(\n        TrieNode memory _branch,\n        uint8 _index,\n        bytes memory _value\n    ) private pure returns (TrieNode memory _updatedNode) {\n        bytes memory encoded = _value.length < 32 ? _value : Lib_RLPWriter.writeBytes(_value);\n        _branch.decoded[_index] = Lib_RLPReader.toRLPItem(encoded);\n        return _makeNode(_branch.decoded);\n    }\n\n    /**\n     * @notice Utility; adds a prefix to a key.\n     * @param _key Key to prefix.\n     * @param _isLeaf Whether or not the key belongs to a leaf.\n     * @return _prefixedKey Prefixed key.\n     */\n    function _addHexPrefix(bytes memory _key, bool _isLeaf)\n        private\n        pure\n        returns (bytes memory _prefixedKey)\n    {\n        uint8 prefix = _isLeaf ? uint8(0x02) : uint8(0x00);\n        uint8 offset = uint8(_key.length % 2);\n        bytes memory prefixed = new bytes(2 - offset);\n        prefixed[0] = bytes1(prefix + offset);\n        return abi.encodePacked(prefixed, _key);\n    }\n\n    /**\n     * @notice Utility; removes a prefix from a path.\n     * @param _path Path to remove the prefix from.\n     * @return _unprefixedKey Unprefixed key.\n     */\n    function _removeHexPrefix(bytes memory _path)\n        private\n        pure\n        returns (bytes memory _unprefixedKey)\n    {\n        if (uint8(_path[0]) % 2 == 0) {\n            return Lib_BytesUtils.slice(_path, 2);\n        } else {\n            return Lib_BytesUtils.slice(_path, 1);\n        }\n    }\n\n    /**\n     * @notice Utility; combines two node arrays. Array lengths are required\n     * because the actual lengths may be longer than the filled lengths.\n     * Array resizing is extremely costly and should be avoided.\n     * @param _a First array to join.\n     * @param _aLength Length of the first array.\n     * @param _b Second array to join.\n     * @param _bLength Length of the second array.\n     * @return _joined Combined node array.\n     */\n    function _joinNodeArrays(\n        TrieNode[] memory _a,\n        uint256 _aLength,\n        TrieNode[] memory _b,\n        uint256 _bLength\n    ) private pure returns (TrieNode[] memory _joined) {\n        TrieNode[] memory ret = new TrieNode[](_aLength + _bLength);\n\n        // Copy elements from the first array.\n        for (uint256 i = 0; i < _aLength; i++) {\n            ret[i] = _a[i];\n        }\n\n        // Copy elements from the second array.\n        for (uint256 i = 0; i < _bLength; i++) {\n            ret[i + _aLength] = _b[i];\n        }\n\n        return ret;\n    }\n}\n"
    },
    "contracts/libraries/utils/Lib_BytesUtils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_BytesUtils\n */\nlibrary Lib_BytesUtils {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    function slice(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    ) internal pure returns (bytes memory) {\n        require(_length + 31 >= _length, \"slice_overflow\");\n        require(_start + _length >= _start, \"slice_overflow\");\n        require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n\n        bytes memory tempBytes;\n\n        assembly {\n            switch iszero(_length)\n            case 0 {\n                // Get a location of some free memory and store it in tempBytes as\n                // Solidity does for memory variables.\n                tempBytes := mload(0x40)\n\n                // The first word of the slice result is potentially a partial\n                // word read from the original array. To read it, we calculate\n                // the length of that partial word and start copying that many\n                // bytes into the array. The first word we copy will start with\n                // data we don't care about, but the last `lengthmod` bytes will\n                // land at the beginning of the contents of the new array. When\n                // we're done copying, we overwrite the full first word with\n                // the actual length of the slice.\n                let lengthmod := and(_length, 31)\n\n                // The multiplication in the next line is necessary\n                // because when slicing multiples of 32 bytes (lengthmod == 0)\n                // the following copy loop was copying the origin's length\n                // and then ending prematurely not copying everything it should.\n                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n                let end := add(mc, _length)\n\n                for {\n                    // The multiplication in the next line has the same exact purpose\n                    // as the one above.\n                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n                } lt(mc, end) {\n                    mc := add(mc, 0x20)\n                    cc := add(cc, 0x20)\n                } {\n                    mstore(mc, mload(cc))\n                }\n\n                mstore(tempBytes, _length)\n\n                //update free-memory pointer\n                //allocating the array padded to 32 bytes like the compiler does now\n                mstore(0x40, and(add(mc, 31), not(31)))\n            }\n            //if we want a zero-length slice let's just return a zero-length array\n            default {\n                tempBytes := mload(0x40)\n\n                //zero out the 32 bytes slice we are about to return\n                //we need to do it because Solidity does not garbage collect\n                mstore(tempBytes, 0)\n\n                mstore(0x40, add(tempBytes, 0x20))\n            }\n        }\n\n        return tempBytes;\n    }\n\n    function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n        if (_start >= _bytes.length) {\n            return bytes(\"\");\n        }\n\n        return slice(_bytes, _start, _bytes.length - _start);\n    }\n\n    function toBytes32(bytes memory _bytes) internal pure returns (bytes32) {\n        if (_bytes.length < 32) {\n            bytes32 ret;\n            assembly {\n                ret := mload(add(_bytes, 32))\n            }\n            return ret;\n        }\n\n        return abi.decode(_bytes, (bytes32)); // will truncate if input length > 32 bytes\n    }\n\n    function toUint256(bytes memory _bytes) internal pure returns (uint256) {\n        return uint256(toBytes32(_bytes));\n    }\n\n    function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n        bytes memory nibbles = new bytes(_bytes.length * 2);\n\n        for (uint256 i = 0; i < _bytes.length; i++) {\n            nibbles[i * 2] = _bytes[i] >> 4;\n            nibbles[i * 2 + 1] = bytes1(uint8(_bytes[i]) % 16);\n        }\n\n        return nibbles;\n    }\n\n    function fromNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n        bytes memory ret = new bytes(_bytes.length / 2);\n\n        for (uint256 i = 0; i < ret.length; i++) {\n            ret[i] = (_bytes[i * 2] << 4) | (_bytes[i * 2 + 1]);\n        }\n\n        return ret;\n    }\n\n    function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n        return keccak256(_bytes) == keccak256(_other);\n    }\n}\n"
    },
    "contracts/libraries/rlp/Lib_RLPWriter.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_RLPWriter\n * @author Bakaoh (with modifications)\n */\nlibrary Lib_RLPWriter {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * RLP encodes a byte string.\n     * @param _in The byte string to encode.\n     * @return The RLP encoded string in bytes.\n     */\n    function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\n        bytes memory encoded;\n\n        if (_in.length == 1 && uint8(_in[0]) < 128) {\n            encoded = _in;\n        } else {\n            encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\n        }\n\n        return encoded;\n    }\n\n    /**\n     * RLP encodes a list of RLP encoded byte byte strings.\n     * @param _in The list of RLP encoded byte strings.\n     * @return The RLP encoded list of items in bytes.\n     */\n    function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\n        bytes memory list = _flatten(_in);\n        return abi.encodePacked(_writeLength(list.length, 192), list);\n    }\n\n    /**\n     * RLP encodes a string.\n     * @param _in The string to encode.\n     * @return The RLP encoded string in bytes.\n     */\n    function writeString(string memory _in) internal pure returns (bytes memory) {\n        return writeBytes(bytes(_in));\n    }\n\n    /**\n     * RLP encodes an address.\n     * @param _in The address to encode.\n     * @return The RLP encoded address in bytes.\n     */\n    function writeAddress(address _in) internal pure returns (bytes memory) {\n        return writeBytes(abi.encodePacked(_in));\n    }\n\n    /**\n     * RLP encodes a uint.\n     * @param _in The uint256 to encode.\n     * @return The RLP encoded uint256 in bytes.\n     */\n    function writeUint(uint256 _in) internal pure returns (bytes memory) {\n        return writeBytes(_toBinary(_in));\n    }\n\n    /**\n     * RLP encodes a bool.\n     * @param _in The bool to encode.\n     * @return The RLP encoded bool in bytes.\n     */\n    function writeBool(bool _in) internal pure returns (bytes memory) {\n        bytes memory encoded = new bytes(1);\n        encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\n        return encoded;\n    }\n\n    /*********************\n     * Private Functions *\n     *********************/\n\n    /**\n     * Encode the first byte, followed by the `len` in binary form if `length` is more than 55.\n     * @param _len The length of the string or the payload.\n     * @param _offset 128 if item is string, 192 if item is list.\n     * @return RLP encoded bytes.\n     */\n    function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\n        bytes memory encoded;\n\n        if (_len < 56) {\n            encoded = new bytes(1);\n            encoded[0] = bytes1(uint8(_len) + uint8(_offset));\n        } else {\n            uint256 lenLen;\n            uint256 i = 1;\n            while (_len / i != 0) {\n                lenLen++;\n                i *= 256;\n            }\n\n            encoded = new bytes(lenLen + 1);\n            encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\n            for (i = 1; i <= lenLen; i++) {\n                encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\n            }\n        }\n\n        return encoded;\n    }\n\n    /**\n     * Encode integer in big endian binary form with no leading zeroes.\n     * @notice TODO: This should be optimized with assembly to save gas costs.\n     * @param _x The integer to encode.\n     * @return RLP encoded bytes.\n     */\n    function _toBinary(uint256 _x) private pure returns (bytes memory) {\n        bytes memory b = abi.encodePacked(_x);\n\n        uint256 i = 0;\n        for (; i < 32; i++) {\n            if (b[i] != 0) {\n                break;\n            }\n        }\n\n        bytes memory res = new bytes(32 - i);\n        for (uint256 j = 0; j < res.length; j++) {\n            res[j] = b[i++];\n        }\n\n        return res;\n    }\n\n    /**\n     * Copies a piece of memory to another location.\n     * @notice From: https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol.\n     * @param _dest Destination location.\n     * @param _src Source location.\n     * @param _len Length of memory to copy.\n     */\n    function _memcpy(\n        uint256 _dest,\n        uint256 _src,\n        uint256 _len\n    ) private pure {\n        uint256 dest = _dest;\n        uint256 src = _src;\n        uint256 len = _len;\n\n        for (; len >= 32; len -= 32) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n            dest += 32;\n            src += 32;\n        }\n\n        uint256 mask;\n        unchecked {\n            mask = 256**(32 - len) - 1;\n        }\n        assembly {\n            let srcpart := and(mload(src), not(mask))\n            let destpart := and(mload(dest), mask)\n            mstore(dest, or(destpart, srcpart))\n        }\n    }\n\n    /**\n     * Flattens a list of byte strings into one byte string.\n     * @notice From: https://github.com/sammayo/solidity-rlp-encoder/blob/master/RLPEncode.sol.\n     * @param _list List of byte strings to flatten.\n     * @return The flattened byte string.\n     */\n    function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\n        if (_list.length == 0) {\n            return new bytes(0);\n        }\n\n        uint256 len;\n        uint256 i = 0;\n        for (; i < _list.length; i++) {\n            len += _list[i].length;\n        }\n\n        bytes memory flattened = new bytes(len);\n        uint256 flattenedPtr;\n        assembly {\n            flattenedPtr := add(flattened, 0x20)\n        }\n\n        for (i = 0; i < _list.length; i++) {\n            bytes memory item = _list[i];\n\n            uint256 listPtr;\n            assembly {\n                listPtr := add(item, 0x20)\n            }\n\n            _memcpy(flattenedPtr, listPtr, item.length);\n            flattenedPtr += _list[i].length;\n        }\n\n        return flattened;\n    }\n}\n"
    },
    "contracts/L1/rollup/IChainStorageContainer.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title IChainStorageContainer\n */\ninterface IChainStorageContainer {\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Sets the container's global metadata field. We're using `bytes27` here because we use five\n     * bytes to maintain the length of the underlying data structure, meaning we have an extra\n     * 27 bytes to store arbitrary data.\n     * @param _globalMetadata New global metadata to set.\n     */\n    function setGlobalMetadata(bytes27 _globalMetadata) external;\n\n    /**\n     * Retrieves the container's global metadata field.\n     * @return Container global metadata field.\n     */\n    function getGlobalMetadata() external view returns (bytes27);\n\n    /**\n     * Retrieves the number of objects stored in the container.\n     * @return Number of objects in the container.\n     */\n    function length() external view returns (uint256);\n\n    /**\n     * Pushes an object into the container.\n     * @param _object A 32 byte value to insert into the container.\n     */\n    function push(bytes32 _object) external;\n\n    /**\n     * Pushes an object into the container. Function allows setting the global metadata since\n     * we'll need to touch the \"length\" storage slot anyway, which also contains the global\n     * metadata (it's an optimization).\n     * @param _object A 32 byte value to insert into the container.\n     * @param _globalMetadata New global metadata for the container.\n     */\n    function push(bytes32 _object, bytes27 _globalMetadata) external;\n\n    /**\n     * Set an object into the container. Function allows setting the global metadata since\n     * we'll need to touch the \"length\" storage slot anyway, which also contains the global\n     * metadata (it's an optimization).\n     * @param _index position.\n     * @param _object A 32 byte value to insert into the container.\n     */\n    function setByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes32 _object\n    ) external;\n\n    /**\n     * Retrieves an object from the container.\n     * @param _index Index of the particular object to access.\n     * @return 32 byte object value.\n     */\n    function get(uint256 _index) external view returns (bytes32);\n\n    /**\n     * Removes all objects after and including a given index.\n     * @param _index Object index to delete from.\n     */\n    function deleteElementsAfterInclusive(uint256 _index) external;\n\n    /**\n     * Removes all objects after and including a given index. Also allows setting the global\n     * metadata field.\n     * @param _index Object index to delete from.\n     * @param _globalMetadata New global metadata for the container.\n     */\n    function deleteElementsAfterInclusive(uint256 _index, bytes27 _globalMetadata) external;\n\n    /**\n     * Sets the container's global metadata field. We're using `bytes27` here because we use five\n     * bytes to maintain the length of the underlying data structure, meaning we have an extra\n     * 27 bytes to store arbitrary data.\n     * @param _chainId identity for the l2 chain.\n     * @param _globalMetadata New global metadata to set.\n     */\n    function setGlobalMetadataByChainId(uint256 _chainId, bytes27 _globalMetadata) external;\n\n    /**\n     * Retrieves the container's global metadata field.\n     * @param _chainId identity for the l2 chain.\n     * @return Container global metadata field.\n     */\n    function getGlobalMetadataByChainId(uint256 _chainId) external view returns (bytes27);\n\n    /**\n     * Retrieves the number of objects stored in the container.\n     * @param _chainId identity for the l2 chain.\n     * @return Number of objects in the container.\n     */\n    function lengthByChainId(uint256 _chainId) external view returns (uint256);\n\n    /**\n     * Pushes an object into the container.\n     * @param _chainId identity for the l2 chain.\n     * @param _object A 32 byte value to insert into the container.\n     */\n    function pushByChainId(uint256 _chainId, bytes32 _object) external;\n\n    /**\n     * Pushes an object into the container. Function allows setting the global metadata since\n     * we'll need to touch the \"length\" storage slot anyway, which also contains the global\n     * metadata (it's an optimization).\n     * @param _chainId identity for the l2 chain.\n     * @param _object A 32 byte value to insert into the container.\n     * @param _globalMetadata New global metadata for the container.\n     */\n    function pushByChainId(\n        uint256 _chainId,\n        bytes32 _object,\n        bytes27 _globalMetadata\n    ) external;\n\n    /**\n     * Retrieves an object from the container.\n     * @param _chainId identity for the l2 chain.\n     * @param _index Index of the particular object to access.\n     * @return 32 byte object value.\n     */\n    function getByChainId(uint256 _chainId, uint256 _index) external view returns (bytes32);\n\n    /**\n     * Removes all objects after and including a given index.\n     * @param _chainId identity for the l2 chain.\n     * @param _index Object index to delete from.\n     */\n    function deleteElementsAfterInclusiveByChainId(uint256 _chainId, uint256 _index) external;\n\n    /**\n     * Removes all objects after and including a given index. Also allows setting the global\n     * metadata field.\n     * @param _chainId identity for the l2 chain.\n     * @param _index Object index to delete from.\n     * @param _globalMetadata New global metadata for the container.\n     */\n    function deleteElementsAfterInclusiveByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    ) external;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal initializer {\n        __Context_init_unchained();\n    }\n\n    function __Context_init_unchained() internal initializer {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n    uint256[50] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     */\n    bool private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Modifier to protect an initializer function from being invoked twice.\n     */\n    modifier initializer() {\n        require(_initializing || !_initialized, \"Initializable: contract is already initialized\");\n\n        bool isTopLevelCall = !_initializing;\n        if (isTopLevelCall) {\n            _initializing = true;\n            _initialized = true;\n        }\n\n        _;\n\n        if (isTopLevelCall) {\n            _initializing = false;\n        }\n    }\n}\n"
    },
    "contracts/MVM/MVM_Verifier.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n/* Contract Imports */\n/* External Imports */\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { iMVM_DiscountOracle } from \"./iMVM_DiscountOracle.sol\";\nimport { Lib_AddressResolver } from \"../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_OVMCodec } from \"../libraries/codec/Lib_OVMCodec.sol\";\nimport { Lib_MerkleTree } from \"../libraries/utils/Lib_MerkleTree.sol\";\nimport { IStateCommitmentChain } from \"../L1/rollup/IStateCommitmentChain.sol\";\n\ncontract MVM_Verifier is Lib_AddressResolver {\n    // second slot\n    address public metis;\n\n    enum SETTLEMENT {\n        NOT_ENOUGH_VERIFIER,\n        SAME_ROOT,\n        AGREE,\n        DISAGREE,\n        PASS\n    }\n\n    event NewChallenge(\n        uint256 cIndex,\n        uint256 chainID,\n        Lib_OVMCodec.ChainBatchHeader header,\n        uint256 timestamp\n    );\n    event Verify1(uint256 cIndex, address verifier);\n    event Verify2(uint256 cIndex, address verifier);\n    event Finalize(uint256 cIndex, address sender, SETTLEMENT result);\n    event Penalize(address sender, uint256 stakeLost);\n    event Reward(address target, uint256 amount);\n    event Claim(address sender, uint256 amount);\n    event Withdraw(address sender, uint256 amount);\n    event Stake(address verifier, uint256 amount);\n    event SlashSequencer(uint256 chainID, address seq);\n\n    /*************\n     * Constants *\n     *************/\n    string public constant CONFIG_OWNER_KEY = \"METIS_MANAGER\";\n\n    //challenge info\n    struct Challenge {\n        address challenger;\n        uint256 chainID;\n        uint256 index;\n        Lib_OVMCodec.ChainBatchHeader header;\n        uint256 timestamp;\n        uint256 numQualifiedVerifiers;\n        uint256 numVerifiers;\n        address[] verifiers;\n        bool done;\n    }\n\n    mapping(address => uint256) public verifier_stakes;\n    mapping(uint256 => mapping(address => bytes)) private challenge_keys;\n    mapping(uint256 => mapping(address => bytes)) private challenge_key_hashes;\n    mapping(uint256 => mapping(address => bytes)) private challenge_hashes;\n\n    mapping(address => uint256) public rewards;\n    mapping(address => uint8) public absence_strikes;\n    mapping(address => uint8) public consensus_strikes;\n\n    // only one active challenge for each chain  chainid=>cIndex\n    mapping(uint256 => uint256) public chain_under_challenge;\n\n    // white list\n    mapping(address => bool) public whitelist;\n    bool useWhiteList;\n\n    address[] public verifiers;\n    Challenge[] public challenges;\n\n    uint256 public verifyWindow = 3600 * 24; // 24 hours of window to complete the each verify phase\n    uint256 public activeChallenges;\n\n    uint256 public minStake;\n    uint256 public seqStake;\n\n    uint256 public numQualifiedVerifiers;\n\n    uint256 FAIL_THRESHOLD = 2; // 1 time grace\n    uint256 ABSENCE_THRESHOLD = 4; // 2 times grace\n\n    modifier onlyManager() {\n        require(\n            msg.sender == resolve(CONFIG_OWNER_KEY),\n            \"MVM_Verifier: Function can only be called by the METIS_MANAGER.\"\n        );\n        _;\n    }\n\n    modifier onlyWhitelisted() {\n        require(isWhiteListed(msg.sender), \"only whitelisted verifiers can call\");\n        _;\n    }\n\n    modifier onlyStaked() {\n        require(isSufficientlyStaked(msg.sender), \"insufficient stake\");\n        _;\n    }\n\n    constructor() Lib_AddressResolver(address(0)) {}\n\n    // add stake as a verifier\n    function verifierStake(uint256 stake) public onlyWhitelisted {\n        require(activeChallenges == 0, \"stake is currently prohibited\"); //ongoing challenge\n        require(stake > 0, \"zero stake not allowed\");\n        require(\n            IERC20(metis).transferFrom(msg.sender, address(this), stake),\n            \"transfer metis failed\"\n        );\n\n        uint256 previousBalance = verifier_stakes[msg.sender];\n        verifier_stakes[msg.sender] += stake;\n\n        require(isSufficientlyStaked(msg.sender), \"insufficient stake to qualify as a verifier\");\n\n        if (previousBalance == 0) {\n            numQualifiedVerifiers++;\n            verifiers.push(msg.sender);\n        }\n\n        emit Stake(msg.sender, stake);\n    }\n\n    // start a new challenge\n    // @param chainID chainid\n    // @param header chainbatch header\n    // @param proposedHash encrypted hash of the correct state\n    // @param keyhash hash of the decryption key\n    //\n    // @dev why do we ask for key and keyhash? because we want verifiers compute the state instead\n    // of just copying from other verifiers.\n    function newChallenge(\n        uint256 chainID,\n        Lib_OVMCodec.ChainBatchHeader calldata header,\n        bytes calldata proposedHash,\n        bytes calldata keyhash\n    ) public onlyWhitelisted onlyStaked {\n        uint256 tempIndex = chain_under_challenge[chainID] - 1;\n        require(\n            tempIndex == 0 || block.timestamp - challenges[tempIndex].timestamp > verifyWindow * 2,\n            \"there is an ongoing challenge\"\n        );\n        if (tempIndex > 0) {\n            finalize(tempIndex);\n        }\n        IStateCommitmentChain stateChain = IStateCommitmentChain(resolve(\"StateCommitmentChain\"));\n\n        // while the root is encrypted, the timestamp is available in the extradata field of the header\n        require(\n            stateChain.insideFraudProofWindow(header),\n            \"the batch is outside of the fraud proof window\"\n        );\n\n        Challenge memory c;\n        c.chainID = chainID;\n        c.challenger = msg.sender;\n        c.timestamp = block.timestamp;\n        c.header = header;\n\n        challenges.push(c);\n        uint256 cIndex = challenges.length - 1;\n\n        // house keeping\n        challenge_hashes[cIndex][msg.sender] = proposedHash;\n        challenge_key_hashes[cIndex][msg.sender] = keyhash;\n        challenges[cIndex].numVerifiers++; // the challenger\n\n        // this will prevent stake change\n        activeChallenges++;\n\n        chain_under_challenge[chainID] = cIndex + 1; // +1 because 0 means no in-progress challenge\n        emit NewChallenge(cIndex, chainID, header, block.timestamp);\n    }\n\n    // phase 1 of the verify, provide an encrypted hash and the hash of the decryption key\n    // @param cIndex index of the challenge\n    // @param hash encrypted hash of the correct state (for the index referred in the challenge)\n    // @param keyhash hash of the decryption key\n    function verify1(\n        uint256 cIndex,\n        bytes calldata hash,\n        bytes calldata keyhash\n    ) public onlyWhitelisted onlyStaked {\n        require(\n            challenge_hashes[cIndex][msg.sender].length == 0,\n            \"verify1 already completed for the sender\"\n        );\n        challenge_hashes[cIndex][msg.sender] = hash;\n        challenge_key_hashes[cIndex][msg.sender] = keyhash;\n        challenges[cIndex].numVerifiers++;\n        emit Verify1(cIndex, msg.sender);\n    }\n\n    // phase 2 of the verify, provide the actual key to decrypt the hash\n    // @param cIndex index of the challenge\n    // @param key the decryption key\n    function verify2(uint256 cIndex, bytes calldata key) public onlyStaked onlyWhitelisted {\n        require(\n            challenges[cIndex].numVerifiers == numQualifiedVerifiers ||\n                block.timestamp - challenges[cIndex].timestamp > verifyWindow,\n            \"phase 2 not ready\"\n        );\n        require(\n            challenge_hashes[cIndex][msg.sender].length > 0,\n            \"you didn't participate in phase 1\"\n        );\n        if (challenge_keys[cIndex][msg.sender].length > 0) {\n            finalize(cIndex);\n            return;\n        }\n\n        //verify whether the key matches the keyhash initially provided.\n        require(\n            sha256(key) == bytes32(challenge_key_hashes[cIndex][msg.sender]),\n            \"key and keyhash don't match\"\n        );\n\n        if (msg.sender == challenges[cIndex].challenger) {\n            //decode the root in the header too\n            challenges[cIndex].header.batchRoot = bytes32(\n                decrypt(abi.encodePacked(challenges[cIndex].header.batchRoot), key)\n            );\n        }\n        challenge_keys[cIndex][msg.sender] = key;\n        challenge_hashes[cIndex][msg.sender] = decrypt(challenge_hashes[cIndex][msg.sender], key);\n        challenges[cIndex].verifiers.push(msg.sender);\n        emit Verify2(cIndex, msg.sender);\n\n        finalize(cIndex);\n    }\n\n    function finalize(uint256 cIndex) internal {\n        Challenge storage challenge = challenges[cIndex];\n\n        require(challenge.done == false, \"challenge is closed\");\n\n        if (\n            challenge.verifiers.length != challenge.numVerifiers &&\n            block.timestamp - challenge.timestamp < verifyWindow * 2\n        ) {\n            // not ready to finalize. do nothing\n            return;\n        }\n\n        IStateCommitmentChain stateChain = IStateCommitmentChain(resolve(\"StateCommitmentChain\"));\n        bytes32 proposedHash = bytes32(challenge_hashes[cIndex][challenge.challenger]);\n\n        uint256 reward = 0;\n\n        address[] memory agrees = new address[](challenge.verifiers.length);\n        uint256 numAgrees = 0;\n        address[] memory disagrees = new address[](challenge.verifiers.length);\n        uint256 numDisagrees = 0;\n        address[] memory penalized = new address[](challenge.verifiers.length);\n        uint256 numPenalized = 0;\n\n        for (uint256 i = 0; i < verifiers.length; i++) {\n            if (!isSufficientlyStaked(verifiers[i]) || !isWhiteListed(verifiers[i])) {\n                // not qualified as a verifier\n                continue;\n            }\n\n            //record the agreement\n            if (bytes32(challenge_hashes[cIndex][verifiers[i]]) == proposedHash) {\n                //agree with the challenger\n                if (absence_strikes[verifiers[i]] > 0) {\n                    absence_strikes[verifiers[i]] -= 1; // slowly clear the strike\n                }\n                agrees[numAgrees] = verifiers[i];\n                numAgrees++;\n            } else if (challenge_keys[cIndex][verifiers[i]].length == 0) {\n                //absent\n                absence_strikes[verifiers[i]] += 2;\n                if (absence_strikes[verifiers[i]] > ABSENCE_THRESHOLD) {\n                    reward += verifier_stakes[verifiers[i]];\n                    penalized[numPenalized] = verifiers[i];\n                    numPenalized++;\n                }\n            } else {\n                //disagree with the challenger\n                if (absence_strikes[verifiers[i]] > 0) {\n                    absence_strikes[verifiers[i]] -= 1; // slowly clear the strike\n                }\n                disagrees[numDisagrees] = verifiers[i];\n                numDisagrees++;\n            }\n        }\n        for (uint256 i = 0; i < numPenalized; i++) {\n            penalize(penalized[i]);\n        }\n\n        if (\n            Lib_OVMCodec.hashBatchHeader(challenge.header) !=\n            stateChain.batches().getByChainId(challenge.chainID, challenge.header.batchIndex)\n        ) {\n            // wrong header, penalize the challenger\n            reward += penalize(challenge.challenger);\n\n            // reward the disagrees. but no penalty on agrees because the input\n            // is garbage.\n            distributeReward(reward, disagrees, challenge.verifiers.length - 1);\n            emit Finalize(cIndex, msg.sender, SETTLEMENT.DISAGREE);\n        } else if (challenge.verifiers.length < (numQualifiedVerifiers * 75) / 100) {\n            // the absent verifiers get a absense strike. no other penalties. already done\n            emit Finalize(cIndex, msg.sender, SETTLEMENT.NOT_ENOUGH_VERIFIER);\n        } else if (proposedHash != challenge.header.batchRoot) {\n            if (numAgrees <= numDisagrees) {\n                // no consensus, challenge failed.\n                for (uint256 i = 0; i < numAgrees; i++) {\n                    consensus_strikes[agrees[i]] += 2;\n                    if (consensus_strikes[agrees[i]] > FAIL_THRESHOLD) {\n                        reward += penalize(agrees[i]);\n                    }\n                }\n                distributeReward(reward, disagrees, disagrees.length);\n                emit Finalize(cIndex, msg.sender, SETTLEMENT.DISAGREE);\n            } else {\n                // reached agreement. delete the batch root and slash the sequencer if the header is still valid\n                if (stateChain.insideFraudProofWindow(challenge.header)) {\n                    // this header needs to be within the window\n                    stateChain.deleteStateBatchByChainId(challenge.chainID, challenge.header);\n\n                    // temporary for the p1 of the decentralization roadmap\n                    if (seqStake > 0) {\n                        reward += seqStake;\n\n                        for (uint256 i = 0; i < numDisagrees; i++) {\n                            consensus_strikes[disagrees[i]] += 2;\n                            if (consensus_strikes[disagrees[i]] > FAIL_THRESHOLD) {\n                                reward += penalize(disagrees[i]);\n                            }\n                        }\n                        distributeReward(reward, agrees, agrees.length);\n                    }\n                    emit Finalize(cIndex, msg.sender, SETTLEMENT.AGREE);\n                } else {\n                    //not in the window anymore. let it pass... no penalty\n                    emit Finalize(cIndex, msg.sender, SETTLEMENT.PASS);\n                }\n            }\n        } else {\n            //wasteful challenge, add consensus_strikes to the challenger\n            consensus_strikes[challenge.challenger] += 2;\n            if (consensus_strikes[challenge.challenger] > FAIL_THRESHOLD) {\n                reward += penalize(challenge.challenger);\n            }\n            distributeReward(reward, challenge.verifiers, challenge.verifiers.length - 1);\n            emit Finalize(cIndex, msg.sender, SETTLEMENT.SAME_ROOT);\n        }\n\n        challenge.done = true;\n        activeChallenges--;\n        chain_under_challenge[challenge.chainID] = 0;\n    }\n\n    function depositSeqStake(uint256 amount) public onlyManager {\n        require(\n            IERC20(metis).transferFrom(msg.sender, address(this), amount),\n            \"transfer metis failed\"\n        );\n        seqStake += amount;\n        emit Stake(msg.sender, amount);\n    }\n\n    function withdrawSeqStake(address to) public onlyManager {\n        require(seqStake > 0, \"no stake\");\n        emit Withdraw(msg.sender, seqStake);\n        uint256 amount = seqStake;\n        seqStake = 0;\n\n        require(IERC20(metis).transfer(to, amount), \"transfer metis failed\");\n    }\n\n    function claim() public {\n        require(rewards[msg.sender] > 0, \"no reward to claim\");\n        uint256 amount = rewards[msg.sender];\n        rewards[msg.sender] = 0;\n\n        require(IERC20(metis).transfer(msg.sender, amount), \"token transfer failed\");\n\n        emit Claim(msg.sender, amount);\n    }\n\n    function withdraw(uint256 amount) public {\n        require(activeChallenges == 0, \"withdraw is currently prohibited\"); //ongoing challenge\n\n        uint256 balance = verifier_stakes[msg.sender];\n        require(balance >= amount, \"insufficient stake to withdraw\");\n\n        if (balance - amount < minStake && balance >= minStake) {\n            numQualifiedVerifiers--;\n            deleteVerifier(msg.sender);\n        }\n        verifier_stakes[msg.sender] -= amount;\n\n        require(IERC20(metis).transfer(msg.sender, amount), \"token transfer failed\");\n    }\n\n    function setMinStake(uint256 _minStake) public onlyManager {\n        minStake = _minStake;\n        uint256 num = 0;\n        if (verifiers.length > 0) {\n            address[] memory arr = new address[](verifiers.length);\n            for (uint256 i = 0; i < verifiers.length; ++i) {\n                if (verifier_stakes[verifiers[i]] >= minStake) {\n                    arr[num] = verifiers[i];\n                    num++;\n                }\n            }\n            if (num < verifiers.length) {\n                delete verifiers;\n                for (uint256 i = 0; i < num; i++) {\n                    verifiers.push(arr[i]);\n                }\n            }\n        }\n        numQualifiedVerifiers = num;\n    }\n\n    // helper\n    function isWhiteListed(address verifier) public view returns (bool) {\n        return !useWhiteList || whitelist[verifier];\n    }\n\n    function isSufficientlyStaked(address target) public view returns (bool) {\n        return (verifier_stakes[target] >= minStake);\n    }\n\n    // set the length of the time windows for each verification phase\n    function setVerifyWindow(uint256 window) public onlyManager {\n        verifyWindow = window;\n    }\n\n    // add the verifier to the whitelist\n    function setWhiteList(address verifier, bool allowed) public onlyManager {\n        whitelist[verifier] = allowed;\n        useWhiteList = true;\n    }\n\n    // allow everyone to be the verifier\n    function disableWhiteList() public onlyManager {\n        useWhiteList = false;\n    }\n\n    function setThreshold(uint256 absence_threshold, uint256 fail_threshold) public onlyManager {\n        ABSENCE_THRESHOLD = absence_threshold;\n        FAIL_THRESHOLD = fail_threshold;\n    }\n\n    function getMerkleRoot(bytes32[] calldata elements) public pure returns (bytes32) {\n        return Lib_MerkleTree.getMerkleRoot(elements);\n    }\n\n    //helper fucntion to encrypt data\n    function encrypt(bytes calldata data, bytes calldata key) public pure returns (bytes memory) {\n        bytes memory encryptedData = data;\n        uint256 j = 0;\n\n        for (uint256 i = 0; i < encryptedData.length; i++) {\n            if (j == key.length) {\n                j = 0;\n            }\n            encryptedData[i] = encryptByte(encryptedData[i], uint8(key[j]));\n            j++;\n        }\n\n        return encryptedData;\n    }\n\n    function encryptByte(bytes1 b, uint8 k) internal pure returns (bytes1) {\n        uint16 temp16 = uint16(uint8(b));\n        temp16 += k;\n\n        if (temp16 > 255) {\n            temp16 -= 256;\n        }\n        return bytes1(uint8(temp16));\n    }\n\n    // helper fucntion to decrypt the data\n    function decrypt(bytes memory data, bytes memory key) public pure returns (bytes memory) {\n        bytes memory decryptedData = data;\n        uint256 j = 0;\n\n        for (uint256 i = 0; i < decryptedData.length; i++) {\n            if (j == key.length) {\n                j = 0;\n            }\n\n            decryptedData[i] = decryptByte(decryptedData[i], uint8(key[j]));\n\n            j++;\n        }\n\n        return decryptedData;\n    }\n\n    function decryptByte(bytes1 b, uint8 k) internal pure returns (bytes1) {\n        uint16 temp16 = uint16(uint8(b));\n        if (temp16 > k) {\n            temp16 -= k;\n        } else {\n            temp16 = 256 - k;\n        }\n\n        return bytes1(uint8(temp16));\n    }\n\n    // calculate the rewards\n    function distributeReward(\n        uint256 amount,\n        address[] memory list,\n        uint256 num\n    ) internal {\n        uint256 reward = amount / num;\n        if (reward == 0) {\n            return;\n        }\n        uint256 total = 0;\n        for (uint256 i; i < list.length; i++) {\n            if (isSufficientlyStaked(list[i])) {\n                rewards[list[i]] += reward;\n                total += reward;\n                emit Reward(list[i], reward);\n            }\n        }\n\n        if (total < amount) {\n            if (isSufficientlyStaked(list[0])) {\n                rewards[list[0]] += total - amount;\n                emit Reward(list[0], total - amount);\n            } else {\n                rewards[list[1]] += total - amount;\n                emit Reward(list[1], total - amount);\n            }\n        }\n    }\n\n    // slash the verifier stake\n    function penalize(address target) internal returns (uint256) {\n        uint256 stake = verifier_stakes[target];\n        verifier_stakes[target] = 0;\n        numQualifiedVerifiers--;\n        deleteVerifier(target);\n        emit Penalize(target, stake);\n\n        return stake;\n    }\n\n    function deleteVerifier(address target) internal {\n        bool hasVerifier = false;\n        uint256 pos = 0;\n        for (uint256 i = 0; i < verifiers.length; i++) {\n            if (verifiers[i] == target) {\n                hasVerifier = true;\n                pos = i;\n                break;\n            }\n        }\n        if (hasVerifier) {\n            for (uint256 i = pos; i < verifiers.length - 1; i++) {\n                verifiers[i] = verifiers[i + 1];\n            }\n            verifiers.pop();\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
    },
    "contracts/libraries/utils/Lib_MerkleTree.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_MerkleTree\n * @author River Keefer\n */\nlibrary Lib_MerkleTree {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Calculates a merkle root for a list of 32-byte leaf hashes.  WARNING: If the number\n     * of leaves passed in is not a power of two, it pads out the tree with zero hashes.\n     * If you do not know the original length of elements for the tree you are verifying, then\n     * this may allow empty leaves past _elements.length to pass a verification check down the line.\n     * Note that the _elements argument is modified, therefore it must not be used again afterwards\n     * @param _elements Array of hashes from which to generate a merkle root.\n     * @return Merkle root of the leaves, with zero hashes for non-powers-of-two (see above).\n     */\n    function getMerkleRoot(bytes32[] memory _elements) internal pure returns (bytes32) {\n        require(_elements.length > 0, \"Lib_MerkleTree: Must provide at least one leaf hash.\");\n\n        if (_elements.length == 1) {\n            return _elements[0];\n        }\n\n        uint256[16] memory defaults = [\n            0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563,\n            0x633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d,\n            0x890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d,\n            0x3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd8,\n            0xecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da,\n            0xdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da5,\n            0x617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d7,\n            0x292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead,\n            0xe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e10,\n            0x7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f82,\n            0xe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e83636516,\n            0x3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c,\n            0xad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e,\n            0xa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab,\n            0x4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c862,\n            0x2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf10\n        ];\n\n        // Reserve memory space for our hashes.\n        bytes memory buf = new bytes(64);\n\n        // We'll need to keep track of left and right siblings.\n        bytes32 leftSibling;\n        bytes32 rightSibling;\n\n        // Number of non-empty nodes at the current depth.\n        uint256 rowSize = _elements.length;\n\n        // Current depth, counting from 0 at the leaves\n        uint256 depth = 0;\n\n        // Common sub-expressions\n        uint256 halfRowSize; // rowSize / 2\n        bool rowSizeIsOdd; // rowSize % 2 == 1\n\n        while (rowSize > 1) {\n            halfRowSize = rowSize / 2;\n            rowSizeIsOdd = rowSize % 2 == 1;\n\n            for (uint256 i = 0; i < halfRowSize; i++) {\n                leftSibling = _elements[(2 * i)];\n                rightSibling = _elements[(2 * i) + 1];\n                assembly {\n                    mstore(add(buf, 32), leftSibling)\n                    mstore(add(buf, 64), rightSibling)\n                }\n\n                _elements[i] = keccak256(buf);\n            }\n\n            if (rowSizeIsOdd) {\n                leftSibling = _elements[rowSize - 1];\n                rightSibling = bytes32(defaults[depth]);\n                assembly {\n                    mstore(add(buf, 32), leftSibling)\n                    mstore(add(buf, 64), rightSibling)\n                }\n\n                _elements[halfRowSize] = keccak256(buf);\n            }\n\n            rowSize = halfRowSize + (rowSizeIsOdd ? 1 : 0);\n            depth++;\n        }\n\n        return _elements[0];\n    }\n\n    /**\n     * Verifies a merkle branch for the given leaf hash.  Assumes the original length\n     * of leaves generated is a known, correct input, and does not return true for indices\n     * extending past that index (even if _siblings would be otherwise valid.)\n     * @param _root The Merkle root to verify against.\n     * @param _leaf The leaf hash to verify inclusion of.\n     * @param _index The index in the tree of this leaf.\n     * @param _siblings Array of sibline nodes in the inclusion proof, starting from depth 0\n     * (bottom of the tree).\n     * @param _totalLeaves The total number of leaves originally passed into.\n     * @return Whether or not the merkle branch and leaf passes verification.\n     */\n    function verify(\n        bytes32 _root,\n        bytes32 _leaf,\n        uint256 _index,\n        bytes32[] memory _siblings,\n        uint256 _totalLeaves\n    ) internal pure returns (bool) {\n        require(_totalLeaves > 0, \"Lib_MerkleTree: Total leaves must be greater than zero.\");\n\n        require(_index < _totalLeaves, \"Lib_MerkleTree: Index out of bounds.\");\n\n        require(\n            _siblings.length == _ceilLog2(_totalLeaves),\n            \"Lib_MerkleTree: Total siblings does not correctly correspond to total leaves.\"\n        );\n\n        bytes32 computedRoot = _leaf;\n\n        for (uint256 i = 0; i < _siblings.length; i++) {\n            if ((_index & 1) == 1) {\n                computedRoot = keccak256(abi.encodePacked(_siblings[i], computedRoot));\n            } else {\n                computedRoot = keccak256(abi.encodePacked(computedRoot, _siblings[i]));\n            }\n\n            _index >>= 1;\n        }\n\n        return _root == computedRoot;\n    }\n\n    /*********************\n     * Private Functions *\n     *********************/\n\n    /**\n     * Calculates the integer ceiling of the log base 2 of an input.\n     * @param _in Unsigned input to calculate the log.\n     * @return ceil(log_base_2(_in))\n     */\n    function _ceilLog2(uint256 _in) private pure returns (uint256) {\n        require(_in > 0, \"Lib_MerkleTree: Cannot compute ceil(log_2) of 0.\");\n\n        if (_in == 1) {\n            return 0;\n        }\n\n        // Find the highest set bit (will be floor(log_2)).\n        // Borrowed with <3 from https://github.com/ethereum/solidity-examples\n        uint256 val = _in;\n        uint256 highest = 0;\n        for (uint256 i = 128; i >= 1; i >>= 1) {\n            if (val & (((uint256(1) << i) - 1) << i) != 0) {\n                highest += i;\n                val >>= i;\n            }\n        }\n\n        // Increment by one if this is not a perfect logarithm.\n        if ((uint256(1) << highest) != _in) {\n            highest += 1;\n        }\n\n        return highest;\n    }\n}\n"
    },
    "contracts/MVM/MVM_StateCommitmentChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../libraries/codec/Lib_OVMCodec.sol\";\nimport { Lib_AddressResolver } from \"../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_MerkleTree } from \"../libraries/utils/Lib_MerkleTree.sol\";\nimport { Lib_Uint } from \"../libraries/utils/Lib_Uint.sol\";\n\n/* Interface Imports */\nimport { IStateCommitmentChain } from \"../L1/rollup/IStateCommitmentChain.sol\";\n// import { ICanonicalTransactionChain } from \"../L1/rollup/ICanonicalTransactionChain.sol\";\nimport { IBondManager } from \"../L1/verification/IBondManager.sol\";\nimport { IChainStorageContainer } from \"../L1/rollup/IChainStorageContainer.sol\";\n\n/**\n * @title MVM_StateCommitmentChain\n * @dev The State Commitment Chain (SCC) contract contains a list of proposed state roots which\n * Proposers assert to be a result of each transaction in the Canonical Transaction Chain (CTC).\n * Elements here have a 1:1 correspondence with transactions in the CTC, and should be the unique\n * state root calculated off-chain by applying the canonical transactions one by one.\n *\n * Runtime target: EVM\n */\ncontract MVM_StateCommitmentChain is IStateCommitmentChain, Lib_AddressResolver {\n    /*************\n     * Constants *\n     *************/\n\n    uint256 public FRAUD_PROOF_WINDOW;\n    uint256 public SEQUENCER_PUBLISH_WINDOW;\n\n    uint256 public DEFAULT_CHAINID = 1088;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     */\n    constructor(\n        address _libAddressManager,\n        uint256 _fraudProofWindow,\n        uint256 _sequencerPublishWindow\n    ) Lib_AddressResolver(_libAddressManager) {\n        FRAUD_PROOF_WINDOW = _fraudProofWindow;\n        SEQUENCER_PUBLISH_WINDOW = _sequencerPublishWindow;\n    }\n\n    function setFraudProofWindow(uint256 window) external {\n        require(msg.sender == resolve(\"METIS_MANAGER\"), \"now allowed\");\n        FRAUD_PROOF_WINDOW = window;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Accesses the batch storage container.\n     * @return Reference to the batch storage container.\n     */\n    function batches() public view returns (IChainStorageContainer) {\n        return IChainStorageContainer(resolve(\"ChainStorageContainer-SCC-batches\"));\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalElements() external view returns (uint256 _totalElements) {\n        return getTotalElementsByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches) {\n        return getTotalBatchesByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getLastSequencerTimestamp() external view returns (uint256 _lastSequencerTimestamp) {\n        return getLastSequencerTimestampByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function appendStateBatch(bytes32[] memory _batch, uint256 _shouldStartAtElement) external {\n        //require (1==0, \"don't use\");\n        string memory proposer = string(\n            abi.encodePacked(Lib_Uint.uint2str(DEFAULT_CHAINID), \"_MVM_Proposer\")\n        );\n        appendStateBatchByChainId(DEFAULT_CHAINID, _batch, _shouldStartAtElement, proposer);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external {\n        deleteStateBatchByChainId(DEFAULT_CHAINID, _batchHeader);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function verifyStateCommitment(\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) external view returns (bool) {\n        return verifyStateCommitmentByChainId(DEFAULT_CHAINID, _element, _batchHeader, _proof);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)\n        public\n        view\n        returns (bool _inside)\n    {\n        (uint256 timestamp, ) = abi.decode(_batchHeader.extraData, (uint256, address));\n\n        require(timestamp != 0, \"Batch header timestamp cannot be zero\");\n        return (timestamp + FRAUD_PROOF_WINDOW) > block.timestamp;\n    }\n\n    function insideFraudProofWindowByChainId(\n        uint256,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) public view override returns (bool _inside) {\n        (uint256 timestamp, ) = abi.decode(_batchHeader.extraData, (uint256, address));\n\n        require(timestamp != 0, \"Batch header timestamp cannot be zero\");\n        return timestamp + FRAUD_PROOF_WINDOW > block.timestamp;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Timestamp of the last batch submitted by the sequencer.\n     */\n    function _getBatchExtraData() internal view returns (uint40, uint40) {\n        return _getBatchExtraDataByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _lastSequencerTimestamp Timestamp of the last batch submitted by the sequencer.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraData(uint40 _totalElements, uint40 _lastSequencerTimestamp)\n        internal\n        pure\n        returns (bytes27)\n    {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _lastSequencerTimestamp))\n            extraData := shl(40, extraData)\n        }\n\n        return extraData;\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _totalElements)\n    {\n        (uint40 totalElements, ) = _getBatchExtraDataByChainId(_chainId);\n        return uint256(totalElements);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _totalBatches)\n    {\n        return batches().lengthByChainId(_chainId);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getLastSequencerTimestampByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _lastSequencerTimestamp)\n    {\n        (, uint40 lastSequencerTimestamp) = _getBatchExtraDataByChainId(_chainId);\n        return uint256(lastSequencerTimestamp);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function appendStateBatchByChainId(\n        uint256 _chainId,\n        bytes32[] memory _batch,\n        uint256 _shouldStartAtElement,\n        string memory proposer\n    ) public override {\n        // Fail fast in to make sure our batch roots aren't accidentally made fraudulent by the\n        // publication of batches by some other user.\n        require(\n            _shouldStartAtElement == getTotalElementsByChainId(_chainId),\n            \"Actual batch start index does not match expected start index.\"\n        );\n\n        address proposerAddr = resolve(proposer);\n\n        // Proposers must have previously staked at the BondManager\n        require(\n            IBondManager(resolve(\"BondManager\")).isCollateralizedByChainId(\n                _chainId,\n                msg.sender,\n                proposerAddr\n            ),\n            \"Proposer does not have enough collateral posted\"\n        );\n\n        require(_batch.length > 0, \"Cannot submit an empty state batch.\");\n\n        // Not check this when submit transaction batch to inbox address\n        // require(\n        //     getTotalElementsByChainId(_chainId) + _batch.length <=\n        //         ICanonicalTransactionChain(resolve(\"CanonicalTransactionChain\"))\n        //             .getTotalElementsByChainId(_chainId),\n        //     \"Number of state roots cannot exceed the number of canonical transactions.\"\n        // );\n\n        // Pass the block's timestamp and the publisher of the data\n        // to be used in the fraud proofs\n        _appendBatchByChainId(\n            _chainId,\n            _batch,\n            abi.encode(block.timestamp, msg.sender),\n            proposerAddr\n        );\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function deleteStateBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) public override {\n        require(\n            msg.sender ==\n                resolve(\n                    string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_FraudVerifier\"))\n                ),\n            \"State batches can only be deleted by the MVM_FraudVerifier.\"\n        );\n\n        require(\n            insideFraudProofWindow(_batchHeader),\n            \"State batches can only be deleted within the fraud proof window.\"\n        );\n\n        _deleteBatchByChainId(_chainId, _batchHeader);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function verifyStateCommitmentByChainId(\n        uint256 _chainId,\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) public view override returns (bool) {\n        require(_isValidBatchHeaderByChainId(_chainId, _batchHeader), \"Invalid batch header.\");\n\n        require(\n            Lib_MerkleTree.verify(\n                _batchHeader.batchRoot,\n                _element,\n                _proof.index,\n                _proof.siblings,\n                _batchHeader.batchSize\n            ),\n            \"Invalid inclusion proof.\"\n        );\n\n        return true;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Timestamp of the last batch submitted by the sequencer.\n     */\n    function _getBatchExtraDataByChainId(uint256 _chainId) internal view returns (uint40, uint40) {\n        bytes27 extraData = batches().getGlobalMetadataByChainId(_chainId);\n\n        uint40 totalElements;\n        uint40 lastSequencerTimestamp;\n        assembly {\n            extraData := shr(40, extraData)\n            totalElements := and(\n                extraData,\n                0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n            )\n            lastSequencerTimestamp := shr(\n                40,\n                and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)\n            )\n        }\n\n        return (totalElements, lastSequencerTimestamp);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _lastSequencerTimestamp Timestamp of the last batch submitted by the sequencer.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraDataByChainId(uint40 _totalElements, uint40 _lastSequencerTimestamp)\n        internal\n        pure\n        returns (bytes27)\n    {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _lastSequencerTimestamp))\n            extraData := shl(40, extraData)\n        }\n\n        return extraData;\n    }\n\n    /**\n     * Appends a batch to the chain.\n     * @param _batch Elements within the batch.\n     * @param _extraData Any extra data to append to the batch.\n     */\n    function _appendBatchByChainId(\n        uint256 _chainId,\n        bytes32[] memory _batch,\n        bytes memory _extraData,\n        address\n    ) internal {\n        (uint40 totalElements, uint40 lastSequencerTimestamp) = _getBatchExtraDataByChainId(\n            _chainId\n        );\n\n        lastSequencerTimestamp = uint40(block.timestamp);\n\n        // For efficiency reasons getMerkleRoot modifies the `_batch` argument in place\n        // while calculating the root hash therefore any arguments passed to it must not\n        // be used again afterwards\n        Lib_OVMCodec.ChainBatchHeader memory batchHeader = Lib_OVMCodec.ChainBatchHeader({\n            batchIndex: getTotalBatchesByChainId(_chainId),\n            batchRoot: Lib_MerkleTree.getMerkleRoot(_batch),\n            batchSize: _batch.length,\n            prevTotalElements: totalElements,\n            extraData: _extraData\n        });\n\n        emit StateBatchAppended(\n            _chainId,\n            batchHeader.batchIndex,\n            batchHeader.batchRoot,\n            batchHeader.batchSize,\n            batchHeader.prevTotalElements,\n            batchHeader.extraData\n        );\n\n        batches().pushByChainId(\n            _chainId,\n            Lib_OVMCodec.hashBatchHeader(batchHeader),\n            _makeBatchExtraDataByChainId(\n                uint40(batchHeader.prevTotalElements + batchHeader.batchSize),\n                lastSequencerTimestamp\n            )\n        );\n    }\n\n    /**\n     * Removes a batch and all subsequent batches from the chain.\n     * @param _batchHeader Header of the batch to remove.\n     */\n    function _deleteBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) internal {\n        require(\n            _batchHeader.batchIndex < batches().lengthByChainId(_chainId),\n            \"Invalid batch index.\"\n        );\n\n        require(_isValidBatchHeaderByChainId(_chainId, _batchHeader), \"Invalid batch header.\");\n\n        batches().deleteElementsAfterInclusiveByChainId(\n            _chainId,\n            _batchHeader.batchIndex,\n            _makeBatchExtraDataByChainId(uint40(_batchHeader.prevTotalElements), 0)\n        );\n\n        emit StateBatchDeleted(_chainId, _batchHeader.batchIndex, _batchHeader.batchRoot);\n    }\n\n    /**\n     * Checks that a batch header matches the stored hash for the given index.\n     * @param _batchHeader Batch header to validate.\n     * @return Whether or not the header matches the stored one.\n     */\n    function _isValidBatchHeaderByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) internal view returns (bool) {\n        return\n            Lib_OVMCodec.hashBatchHeader(_batchHeader) ==\n            batches().getByChainId(_chainId, _batchHeader.batchIndex);\n    }\n}\n"
    },
    "contracts/libraries/utils/Lib_Uint.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_Uint\n * @author\n */\nlibrary Lib_Uint {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Convert uint to string\n     * @param _i uint value.\n     * @return _uintAsString string momery value.\n     */\n    function uint2str(uint256 _i) internal pure returns (string memory _uintAsString) {\n        if (_i == 0) {\n            return \"0\";\n        }\n        uint256 j = _i;\n        uint256 len;\n        while (j != 0) {\n            len++;\n            j /= 10;\n        }\n        bytes memory bstr = new bytes(len);\n        uint256 k = len;\n        while (_i != 0) {\n            k = k - 1;\n            uint8 temp = (48 + uint8(_i - (_i / 10) * 10));\n            bytes1 b1 = bytes1(temp);\n            bstr[k] = b1;\n            _i /= 10;\n        }\n        return string(bstr);\n    }\n}\n"
    },
    "contracts/L1/verification/IBondManager.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title IBondManager\n */\ninterface IBondManager {\n    /********************\n     * Public Functions *\n     ********************/\n\n    function isCollateralized(address _who) external view returns (bool);\n\n    function isCollateralizedByChainId(\n        uint256 _chainId,\n        address _who,\n        address _prop\n    ) external view returns (bool);\n}\n"
    },
    "contracts/MVM/MVM_CanonicalTransaction.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_AddressResolver } from \"../libraries/resolver/Lib_AddressResolver.sol\";\n\n/* Interface Imports */\nimport { iMVM_CanonicalTransaction } from \"./iMVM_CanonicalTransaction.sol\";\nimport { ICanonicalTransactionChain } from \"../L1/rollup/ICanonicalTransactionChain.sol\";\nimport { IChainStorageContainer } from \"../L1/rollup/IChainStorageContainer.sol\";\nimport { StateCommitmentChain } from \"../L1/rollup/StateCommitmentChain.sol\";\nimport { Lib_MerkleTree } from \"../libraries/utils/Lib_MerkleTree.sol\";\nimport { Lib_Uint } from \"../libraries/utils/Lib_Uint.sol\";\n\ncontract MVM_CanonicalTransaction is iMVM_CanonicalTransaction, Lib_AddressResolver {\n    /*************\n     * Constants *\n     *************/\n\n    string public constant CONFIG_OWNER_KEY = \"METIS_MANAGER\";\n\n    // lock seconds when begin to submit batch tx data slice\n    uint256 public constant TXDATA_SUBMIT_TIMEOUT = 1800;\n\n    /*************\n     * Variables *\n     *************/\n\n    // submit tx data slice size (in bytes)\n    uint256 public txDataSliceSize;\n    // stake duration seconds for sequencer submit batch tx data\n    uint256 public stakeSeqSeconds;\n    // verifier stake base cost for a batch tx data requirement (in ETH)\n    uint256 public stakeBaseCost;\n    // submit tx data slice count (a whole tx batch)\n    uint256 public txDataSliceCount;\n    // submit tx batch size (in bytes)\n    uint256 public txBatchSize;\n    // verifier stake unit cost for a batch tx data requirement (in ETH)\n    uint256 public stakeUnitCost;\n\n    bool useWhiteList;\n\n    /***************\n     * Queue State *\n     ***************/\n\n    // white list\n    mapping(address => bool) public whitelist;\n\n    // mapping(address => uint256) private addressChains;\n\n    // verifier stakes statistic\n    mapping(address => uint256) private verifierStakes;\n\n    // batch element information for validation queue\n    mapping(uint256 => mapping(uint256 => BatchElement)) queueBatchElement;\n\n    // tx data request stake queue\n    mapping(uint256 => mapping(uint256 => TxDataRequestStake)) queueTxDataRequestStake;\n\n    // tx data for verification queue\n    mapping(uint256 => mapping(uint256 => TxDataSlice)) queueTxData;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor() Lib_AddressResolver(address(0)) {}\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    modifier onlyManager() {\n        require(\n            msg.sender == resolve(CONFIG_OWNER_KEY),\n            \"MVM_CanonicalTransaction: Function can only be called by the METIS_MANAGER.\"\n        );\n        _;\n    }\n\n    modifier onlyWhitelisted() {\n        require(isWhiteListed(msg.sender), \"only whitelisted verifiers can call\");\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n    /**\n    receive() external payable {\n        // msg.sender\n        if (msg.sender == resolve('MVM_DiscountOracle')) {\n            uint256 _chainId = getAddressChainId(msg.sender);\n            if (_chainId > 0) {\n                address _to = resolve(string(abi.encodePacked(Lib_Uint.uint2str(_chainId),\"_MVM_Sequencer_Wrapper\")));\n                if (_to != address(0) && _to != address(this)) {\n                    _to.call{value: msg.value}(\"\");\n                }\n            }\n        }\n    }\n\n    function setAddressChainId(address _address, uint256 _chainId)  override public onlyManager {\n        require(_address != address(0), \"address not available\");\n        require(_chainId > 0, \"chainId not available\");\n        require(addressChains[_address] != _chainId, \"no change\");\n        addressChains[_address] = _chainId;\n    }\n\n    function getAddressChainId(address _address) override public view returns (uint256) {\n        return addressChains[_address];\n    }\n    */\n\n    function setStakeBaseCost(uint256 _stakeBaseCost) public override onlyManager {\n        // 1e16 = 0.01 ether\n        // require(_stakeBaseCost >= 1e16, \"stake base cost should gte 1e16\");\n        stakeBaseCost = _stakeBaseCost;\n    }\n\n    function getStakeBaseCost() public view override returns (uint256) {\n        return stakeBaseCost;\n    }\n\n    function setStakeUnitCost(uint256 _stakeUnitCost) public override onlyManager {\n        // 1e16 = 0.01 ether\n        stakeUnitCost = _stakeUnitCost;\n    }\n\n    function getStakeUnitCost() public view override returns (uint256) {\n        return stakeUnitCost;\n    }\n\n    function getStakeCostByBatch(uint256 _chainId, uint256 _batchIndex)\n        public\n        view\n        override\n        returns (uint256)\n    {\n        require(stakeBaseCost > 0, \"stake base cost not config yet\");\n        require(\n            queueBatchElement[_chainId][_batchIndex].txBatchTime > 0,\n            \"batch element does not exist\"\n        );\n        return stakeBaseCost + queueBatchElement[_chainId][_batchIndex].txBatchSize * stakeUnitCost;\n    }\n\n    function setTxDataSliceSize(uint256 _size) public override onlyManager {\n        require(_size > 0, \"slice size should gt 0\");\n        require(_size != txDataSliceSize, \"slice size has not changed\");\n        txDataSliceSize = _size;\n    }\n\n    function getTxDataSliceSize() public view override returns (uint256) {\n        return txDataSliceSize;\n    }\n\n    function setTxDataSliceCount(uint256 _count) public override onlyManager {\n        require(_count > 0, \"slice count should gt 0\");\n        require(_count != txDataSliceCount, \"slice count has not changed\");\n        txDataSliceCount = _count;\n    }\n\n    function getTxDataSliceCount() public view override returns (uint256) {\n        return txDataSliceCount;\n    }\n\n    function setTxBatchSize(uint256 _size) public override onlyManager {\n        require(_size > 0, \"batch size should gt 0\");\n        require(_size != txBatchSize, \"batch size has not changed\");\n        txBatchSize = _size;\n    }\n\n    function getTxBatchSize() public view override returns (uint256) {\n        return txBatchSize;\n    }\n\n    function setStakeSeqSeconds(uint256 _seconds) public override onlyManager {\n        require(_seconds > 0, \"seconds should gt 0\");\n        require(_seconds != stakeSeqSeconds, \"seconds has not changed\");\n        stakeSeqSeconds = _seconds;\n    }\n\n    function getStakeSeqSeconds() public view override returns (uint256) {\n        return stakeSeqSeconds;\n    }\n\n    function isWhiteListed(address _verifier) public view override returns (bool) {\n        return !useWhiteList || whitelist[_verifier];\n    }\n\n    function setWhiteList(address _verifier, bool _allowed) public override onlyManager {\n        whitelist[_verifier] = _allowed;\n        useWhiteList = true;\n    }\n\n    function disableWhiteList() public override onlyManager {\n        useWhiteList = false;\n    }\n\n    function appendSequencerBatchByChainId() public override {\n        uint256 _chainId;\n        uint40 shouldStartAtElement;\n        uint24 totalElementsToAppend;\n        uint24 numContexts;\n        uint256 batchTime;\n        uint256 _dataSize;\n        uint256 txSize;\n        bytes32 root;\n        assembly {\n            _dataSize := calldatasize()\n            _chainId := calldataload(4)\n            shouldStartAtElement := shr(216, calldataload(36))\n            totalElementsToAppend := shr(232, calldataload(41))\n            numContexts := shr(232, calldataload(44))\n        }\n        require(\n            msg.sender ==\n                resolve(\n                    string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Sequencer_Wrapper\"))\n                ),\n            \"Function can only be called by the Sequencer.\"\n        );\n        uint256 posTs = 47 + 16 * numContexts;\n        if (_dataSize > posTs) {\n            // when tx count = 0, there is no hash!\n            // string len: [13]{milliseconds}-[1]{0}-[8]{sizeOfData}-[64]{hash}-[64]{root}\n            uint256 posTxSize = 7 + posTs;\n            uint256 posRoot = 11 + posTs;\n            assembly {\n                batchTime := shr(204, calldataload(posTs))\n                txSize := shr(224, calldataload(posTxSize))\n                root := calldataload(posRoot)\n            }\n\n            // check batch size\n            require(txSize / 2 <= txBatchSize, \"size of tx data is too large\");\n        }\n\n        address ctc = resolve(\"CanonicalTransactionChain\");\n        IChainStorageContainer batchesRef = ICanonicalTransactionChain(ctc).batches();\n        uint256 batchIndex = batchesRef.lengthByChainId(_chainId);\n        {\n            // ctc call\n            (bool success, bytes memory result) = ctc.call(msg.data);\n            if (success == false) {\n                assembly {\n                    let ptr := mload(0x40)\n                    let size := returndatasize()\n                    returndatacopy(ptr, 0, size)\n                    revert(ptr, size)\n                }\n            }\n        }\n\n        // save\n        queueBatchElement[_chainId][batchIndex] = BatchElement({\n            shouldStartAtElement: shouldStartAtElement,\n            totalElementsToAppend: totalElementsToAppend,\n            txBatchSize: txSize,\n            txBatchTime: batchTime,\n            root: root,\n            timestamp: block.timestamp\n        });\n\n        emit AppendBatchElement(\n            _chainId,\n            batchIndex,\n            shouldStartAtElement,\n            totalElementsToAppend,\n            txSize,\n            batchTime,\n            root\n        );\n    }\n\n    function setBatchTxDataForStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data,\n        uint256 _leafIndex,\n        uint256 _totalLeaves,\n        bytes32[] memory _proof\n    ) public override {\n        require(\n            msg.sender ==\n                resolve(\n                    string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Sequencer_Wrapper\"))\n                ),\n            \"Function can only be called by the Sequencer.\"\n        );\n        // check stake\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].timestamp > 0,\n            \"there is no stake for this block number\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].batchIndex == _batchIndex,\n            \"incorrect batch index\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.INIT,\n            \"not allowed to submit\"\n        );\n        // sequencer can submit at any time\n        // require(queueTxDataRequestStake[_chainId][_blockNumber].endtime >= block.timestamp, \"can not submit out of sequencer submit protection\");\n\n        _setBatchTxData(\n            _chainId,\n            _batchIndex,\n            _blockNumber,\n            _data,\n            _leafIndex,\n            _totalLeaves,\n            _proof,\n            true\n        );\n\n        if (queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.INIT) {\n            require(\n                queueTxDataRequestStake[_chainId][_blockNumber].amount <=\n                    verifierStakes[queueTxDataRequestStake[_chainId][_blockNumber].sender],\n                \"insufficient stake\"\n            );\n            require(\n                queueTxDataRequestStake[_chainId][_blockNumber].amount <= address(this).balance,\n                \"insufficient balance\"\n            );\n            queueTxDataRequestStake[_chainId][_blockNumber].status = STAKESTATUS.SEQ_SET;\n            if (queueTxDataRequestStake[_chainId][_blockNumber].amount > 0) {\n                verifierStakes[\n                    queueTxDataRequestStake[_chainId][_blockNumber].sender\n                ] -= queueTxDataRequestStake[_chainId][_blockNumber].amount;\n                // transfer from contract to sender ETHER and record\n                (bool success, ) = payable(msg.sender).call{\n                    value: queueTxDataRequestStake[_chainId][_blockNumber].amount\n                }(\"\");\n                require(success, \"insufficient balance\");\n                queueTxDataRequestStake[_chainId][_blockNumber].amount = 0;\n            }\n        }\n\n        emit SetBatchTxData(\n            msg.sender,\n            _chainId,\n            _batchIndex,\n            _blockNumber,\n            queueTxDataRequestStake[_chainId][_blockNumber].amount,\n            true,\n            true\n        );\n    }\n\n    function setBatchTxDataForVerifier(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data\n    ) public override {\n        require(\n            msg.sender !=\n                resolve(\n                    string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Sequencer_Wrapper\"))\n                ),\n            \"Function can not be called by the Sequencer.\"\n        );\n        // check stake\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].timestamp > 0,\n            \"there is no stake for this block number\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].batchIndex == _batchIndex,\n            \"incorrect batch index\"\n        );\n        // require(queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.INIT, \"not allowed to submit\");\n        // require(queueTxDataRequestStake[_chainId][_blockNumber].sender == msg.sender, \"can not submit with other's stake\");\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].endtime < block.timestamp,\n            \"can not submit during sequencer submit protection\"\n        );\n        if (queueTxDataRequestStake[_chainId][_blockNumber].sender != msg.sender) {\n            // other verifier can submit in double window times\n            require(\n                queueTxDataRequestStake[_chainId][_blockNumber].endtime + stakeSeqSeconds <\n                    block.timestamp,\n                \"can not submit during staker submit protection\"\n            );\n        }\n\n        _setBatchTxData(_chainId, _batchIndex, _blockNumber, _data, 0, 0, new bytes32[](0), false);\n\n        if (queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.INIT) {\n            queueTxDataRequestStake[_chainId][_blockNumber].status = STAKESTATUS.VERIFIER_SET;\n\n            address claimer = queueTxDataRequestStake[_chainId][_blockNumber].sender;\n            if (\n                queueTxDataRequestStake[_chainId][_blockNumber].amount <= verifierStakes[claimer] &&\n                queueTxDataRequestStake[_chainId][_blockNumber].amount > 0\n            ) {\n                require(\n                    queueTxDataRequestStake[_chainId][_blockNumber].amount <= address(this).balance,\n                    \"insufficient balance\"\n                );\n                verifierStakes[claimer] -= queueTxDataRequestStake[_chainId][_blockNumber].amount;\n                // transfer from contract to sender ETHER and record\n                (bool success, ) = payable(claimer).call{\n                    value: queueTxDataRequestStake[_chainId][_blockNumber].amount\n                }(\"\");\n                require(success, \"insufficient balance\");\n                queueTxDataRequestStake[_chainId][_blockNumber].amount = 0;\n            }\n        }\n\n        emit SetBatchTxData(\n            msg.sender,\n            _chainId,\n            _batchIndex,\n            _blockNumber,\n            queueTxDataRequestStake[_chainId][_blockNumber].amount,\n            false,\n            false\n        );\n    }\n\n    function _setBatchTxData(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data,\n        uint256 _leafIndex,\n        uint256 _totalLeaves,\n        bytes32[] memory _proof,\n        bool _requireVerify\n    ) internal {\n        require(_data.length > 0, \"empty data\");\n        // check queue BatchElement\n        require(\n            queueBatchElement[_chainId][_batchIndex].txBatchTime > 0,\n            \"batch element does not exist\"\n        );\n        require(\n            queueBatchElement[_chainId][_batchIndex].totalElementsToAppend > 0,\n            \"batch total element to append should not be zero\"\n        );\n\n        // sequencer protect\n        if (queueTxData[_chainId][_blockNumber].timestamp > 0) {\n            require(queueTxData[_chainId][_blockNumber].verified == false, \"tx data verified\");\n            if (queueTxData[_chainId][_blockNumber].sender != msg.sender) {\n                require(\n                    queueTxData[_chainId][_blockNumber].timestamp + TXDATA_SUBMIT_TIMEOUT >\n                        block.timestamp,\n                    \"in submitting\"\n                );\n\n                // change sumbitter\n                queueTxData[_chainId][_blockNumber].sender = msg.sender;\n                queueTxData[_chainId][_blockNumber].blockNumber = _blockNumber;\n                queueTxData[_chainId][_blockNumber].batchIndex = _batchIndex;\n                queueTxData[_chainId][_blockNumber].timestamp = block.timestamp;\n                queueTxData[_chainId][_blockNumber].txData = _data;\n                queueTxData[_chainId][_blockNumber].verified = false;\n            } else {\n                queueTxData[_chainId][_blockNumber].txData = _data;\n                // verified restore to false\n                queueTxData[_chainId][_blockNumber].verified = false;\n            }\n        } else {\n            queueTxData[_chainId][_blockNumber] = TxDataSlice({\n                sender: msg.sender,\n                blockNumber: _blockNumber,\n                batchIndex: _batchIndex,\n                timestamp: block.timestamp,\n                txData: _data,\n                verified: false\n            });\n        }\n        if (_requireVerify) {\n            bytes32 currLeaf = keccak256(abi.encodePacked(_blockNumber, _data));\n            bool verified = Lib_MerkleTree.verify(\n                queueBatchElement[_chainId][_batchIndex].root,\n                currLeaf,\n                _leafIndex,\n                _proof,\n                _totalLeaves\n            );\n            require(verified == true, \"tx data verify failed\");\n\n            // save verified status\n            queueTxData[_chainId][_blockNumber].verified = true;\n        }\n    }\n\n    function getBatchTxData(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) external view override returns (bytes memory txData, bool verified) {\n        require(queueTxData[_chainId][_blockNumber].timestamp != 0, \"tx data does not exist\");\n        require(\n            queueTxData[_chainId][_blockNumber].batchIndex == _batchIndex,\n            \"incorrect batch index\"\n        );\n        return (\n            queueTxData[_chainId][_blockNumber].txData,\n            queueTxData[_chainId][_blockNumber].verified\n        );\n    }\n\n    function checkBatchTxHash(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data\n    ) external view override returns (bytes32 txHash, bool verified) {\n        require(queueTxData[_chainId][_blockNumber].timestamp != 0, \"tx data does not exist\");\n        require(\n            queueTxData[_chainId][_blockNumber].batchIndex == _batchIndex,\n            \"incorrect batch index\"\n        );\n        return (\n            keccak256(abi.encodePacked(_blockNumber, _data)),\n            queueTxData[_chainId][_blockNumber].verified\n        );\n    }\n\n    function setBatchTxDataVerified(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bool _verified\n    ) public override onlyManager {\n        require(queueTxData[_chainId][_blockNumber].timestamp != 0, \"tx data does not exist\");\n        require(\n            queueTxData[_chainId][_blockNumber].batchIndex == _batchIndex,\n            \"incorrect batch index\"\n        );\n        require(\n            queueTxData[_chainId][_blockNumber].verified != _verified,\n            \"verified status not change\"\n        );\n\n        queueTxData[_chainId][_blockNumber].verified = _verified;\n    }\n\n    function verifierStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) public payable override onlyWhitelisted {\n        uint256 _amount = msg.value;\n        uint256 stakeCost = getStakeCostByBatch(_chainId, _batchIndex);\n        require(stakeBaseCost > 0, \"stake base cost not config yet\");\n        require(stakeCost == _amount, \"stake cost incorrect\");\n        require(stakeSeqSeconds > 0, \"sequencer submit seconds not config yet\");\n        // check queue BatchElement\n        require(\n            queueBatchElement[_chainId][_batchIndex].txBatchTime > 0,\n            \"batch element does not exist\"\n        );\n        // check block number in batch range, block number = index + 1\n        require(\n            queueBatchElement[_chainId][_batchIndex].totalElementsToAppend +\n                queueBatchElement[_chainId][_batchIndex].shouldStartAtElement >=\n                _blockNumber &&\n                queueBatchElement[_chainId][_batchIndex].shouldStartAtElement < _blockNumber,\n            \"block number is not in this batch\"\n        );\n        if (queueTxDataRequestStake[_chainId][_blockNumber].timestamp > 0) {\n            require(\n                queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.PAYBACK,\n                \"there is a stake for this batch index\"\n            );\n        }\n\n        //check window\n        StateCommitmentChain stateChain = StateCommitmentChain(resolve(\"StateCommitmentChain\"));\n        require(\n            queueBatchElement[_chainId][_batchIndex].timestamp + stateChain.FRAUD_PROOF_WINDOW() >\n                block.timestamp,\n            \"the batch is outside of the fraud proof window\"\n        );\n\n        queueTxDataRequestStake[_chainId][_blockNumber] = TxDataRequestStake({\n            sender: msg.sender,\n            blockNumber: _blockNumber,\n            batchIndex: _batchIndex,\n            timestamp: block.timestamp,\n            endtime: block.timestamp + stakeSeqSeconds,\n            amount: _amount,\n            status: STAKESTATUS.INIT\n        });\n        verifierStakes[msg.sender] += _amount;\n\n        emit VerifierStake(msg.sender, _chainId, _batchIndex, _blockNumber, _amount);\n    }\n\n    function withdrawStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) public override {\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].timestamp > 0,\n            \"there is no stake for this batch index\"\n        );\n        require(queueTxDataRequestStake[_chainId][_blockNumber].amount > 0, \"stake amount is zero\");\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.INIT,\n            \"withdrawals are not allowed\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].sender == msg.sender,\n            \"can not withdraw other's stake\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].endtime < block.timestamp,\n            \"can not withdraw during submit protection\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].amount <= verifierStakes[msg.sender],\n            \"insufficient stake\"\n        );\n\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].amount <= address(this).balance,\n            \"insufficient balance\"\n        );\n        queueTxDataRequestStake[_chainId][_blockNumber].status = STAKESTATUS.PAYBACK;\n        verifierStakes[msg.sender] -= queueTxDataRequestStake[_chainId][_blockNumber].amount;\n        // transfer from contract to sender ETHER and record\n        (bool success, ) = payable(msg.sender).call{\n            value: queueTxDataRequestStake[_chainId][_blockNumber].amount\n        }(\"\");\n        require(success, \"insufficient balance\");\n        queueTxDataRequestStake[_chainId][_blockNumber].amount = 0;\n    }\n}\n"
    },
    "contracts/MVM/iMVM_CanonicalTransaction.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Contract Imports */\n\n/* External Imports */\n\n/**\n * @title ICanonicalTransactionChain\n */\ninterface iMVM_CanonicalTransaction {\n    /*********\n     * Enums *\n     *********/\n\n    enum STAKESTATUS {\n        INIT,\n        SEQ_SET,\n        VERIFIER_SET,\n        PAYBACK\n    }\n\n    /**********\n     * Events *\n     **********/\n\n    event VerifierStake(\n        address _sender,\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        uint256 _amount\n    );\n\n    // default : stakeAmount=0, verified=true, sequencer=true\n    // sequencer response for stake: stakeAmount>0, verified=true, sequencer=true\n    // verifier response for stake timeout: stakeAmount>0, verified=false, sequencer=false\n    event SetBatchTxData(\n        address _sender,\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        uint256 _stakeAmount,\n        bool _verified,\n        bool _sequencer\n    );\n\n    event AppendBatchElement(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint40 _shouldStartAtElement,\n        uint24 _totalElementsToAppend,\n        uint256 _txBatchSize,\n        uint256 _txBatchTime,\n        bytes32 _root\n    );\n\n    /***********\n     * Structs *\n     ***********/\n\n    // locker the same sender for 30 min\n    struct TxDataSlice {\n        address sender;\n        uint256 blockNumber;\n        uint256 batchIndex;\n        uint256 timestamp;\n        bytes txData;\n        bool verified;\n    }\n\n    struct TxDataRequestStake {\n        address sender;\n        uint256 blockNumber;\n        uint256 batchIndex;\n        uint256 timestamp;\n        uint256 endtime;\n        uint256 amount;\n        STAKESTATUS status;\n    }\n\n    struct BatchElement {\n        uint40 shouldStartAtElement;\n        uint24 totalElementsToAppend;\n        uint256 txBatchSize;\n        uint256 txBatchTime; // sequencer client encode timestamp(ms)\n        bytes32 root; // merkle hash root with [hash(txDataBytes + blockNumber)]\n        uint256 timestamp; // block timestamp\n    }\n\n    /*******************************\n     * Authorized Setter Functions *\n     *******************************/\n\n    /**\n     * Sets address's chain id.\n     * @param _address contract address.\n     * @param _chainId chain id.\n     */\n    // function setAddressChainId(address _address, uint256 _chainId) external;\n\n    /**\n     * Gets address's chain id.\n     */\n    // function getAddressChainId(address _address) external view returns (uint256);\n\n    /**\n     * Sets the verifier stake base cost of ETH.\n     * @param _stakeBaseCost Stake base cost for verifier.\n     */\n    function setStakeBaseCost(uint256 _stakeBaseCost) external;\n\n    /**\n     * Gets the verifier stake base cost of ETH.\n     */\n    function getStakeBaseCost() external view returns (uint256);\n\n    /**\n     * Sets the verifier stake unit cost of ETH.\n     * @param _stakeUnitCost Stake cost for verifier.\n     */\n    function setStakeUnitCost(uint256 _stakeUnitCost) external;\n\n    /**\n     * Gets the verifier stake unit cost of ETH for per storage unit.\n     */\n    function getStakeUnitCost() external view returns (uint256);\n\n    /**\n     * Gets the verifier stake cost of ETH by batch index.\n     */\n    function getStakeCostByBatch(uint256 _chainId, uint256 _batchIndex)\n        external\n        view\n        returns (uint256);\n\n    /**\n     * Sets batch transaction data slice size per submit.\n     * @param _size Slice size of batch transaction data.\n     */\n    function setTxDataSliceSize(uint256 _size) external;\n\n    /**\n     * Gets batch transaction data slice size per submit.\n     */\n    function getTxDataSliceSize() external view returns (uint256);\n\n    /**\n     * Sets batch size per batch.\n     * @param _size Batch size of batch.\n     */\n    function setTxBatchSize(uint256 _size) external;\n\n    /**\n     * Gets batch size per batch.\n     */\n    function getTxBatchSize() external view returns (uint256);\n\n    /**\n     * Sets slice count per batch transaction data.\n     * @param _count Slice count per batch transaction data.\n     */\n    function setTxDataSliceCount(uint256 _count) external;\n\n    /**\n     * Gets slice count per batch transaction data.\n     */\n    function getTxDataSliceCount() external view returns (uint256);\n\n    /**\n     * Sets seconds can submit transaction data after staking.\n     * @param _seconds Seconds the Sequencer can sumbit transaction data after verifier staking.\n     */\n    function setStakeSeqSeconds(uint256 _seconds) external;\n\n    /**\n     * Gets seconds can submit transaction data after staking.\n     * @return Seconds the Sequencer can sumbit transaction data after verifier staking.\n     */\n    function getStakeSeqSeconds() external view returns (uint256);\n\n    function isWhiteListed(address _verifier) external view returns (bool);\n\n    // add the verifier to the whitelist\n    function setWhiteList(address _verifier, bool _allowed) external;\n\n    // allow everyone to be the verifier\n    function disableWhiteList() external;\n\n    /**\n     * Allows the sequencer to append a batch of transactions.\n     * @dev This function uses a custom encoding scheme for efficiency reasons.\n     */\n    function appendSequencerBatchByChainId() external;\n\n    /**\n     * Sets batch tx data for stake.\n     * @param _chainId chain id.\n     * @param _batchIndex batch index of CTC.\n     * @param _blockNumber slice index.\n     * @param _data tx data hex.\n     */\n    function setBatchTxDataForStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data,\n        uint256 _leafIndex,\n        uint256 _totalLeaves,\n        bytes32[] memory _proof\n    ) external;\n\n    /**\n     * Sets batch tx data for verifier.\n     * @param _chainId chain id.\n     * @param _batchIndex batch index of CTC.\n     * @param _blockNumber slice index.\n     * @param _data tx data hex.\n     */\n    function setBatchTxDataForVerifier(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data\n    ) external;\n\n    /**\n     * Gets batch tx data.\n     * @param _chainId chain id.\n     * @param _batchIndex batch index of CTC.\n     * @param _blockNumber block number.\n     * @return txData\n     * @return verified\n     */\n    function getBatchTxData(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) external view returns (bytes memory txData, bool verified);\n\n    function checkBatchTxHash(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data\n    ) external view returns (bytes32 txHash, bool verified);\n\n    function setBatchTxDataVerified(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bool _verified\n    ) external;\n\n    /**\n     * Stake by verifier.\n     * @param _chainId chain id.\n     * @param _batchIndex batch index of CTC.\n     * @param _blockNumber block number.\n     */\n    function verifierStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) external payable;\n\n    /**\n     * Withdraw stake by verifier.\n     * @param _chainId chain id.\n     * @param _batchIndex batch index of CTC.\n     * @param _blockNumber block number.\n     */\n    function withdrawStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) external;\n}\n"
    },
    "contracts/L1/rollup/StateCommitmentChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\nimport { Lib_AddressResolver } from \"../../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_MerkleTree } from \"../../libraries/utils/Lib_MerkleTree.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/* Interface Imports */\nimport { IStateCommitmentChain } from \"./IStateCommitmentChain.sol\";\nimport { ICanonicalTransactionChain } from \"./ICanonicalTransactionChain.sol\";\nimport { IBondManager } from \"../verification/IBondManager.sol\";\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title StateCommitmentChain\n * @dev The State Commitment Chain (SCC) contract contains a list of proposed state roots which\n * Proposers assert to be a result of each transaction in the Canonical Transaction Chain (CTC).\n * Elements here have a 1:1 correspondence with transactions in the CTC, and should be the unique\n * state root calculated off-chain by applying the canonical transactions one by one.\n *\n * Runtime target: EVM\n */\ncontract StateCommitmentChain is IStateCommitmentChain, Lib_AddressResolver {\n    /*************\n     * Constants *\n     *************/\n\n    uint256 public FRAUD_PROOF_WINDOW;\n    uint256 public SEQUENCER_PUBLISH_WINDOW;\n\n    uint256 public DEFAULT_CHAINID = 1088;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     */\n    constructor(\n        address _libAddressManager,\n        uint256 _fraudProofWindow,\n        uint256 _sequencerPublishWindow\n    ) Lib_AddressResolver(_libAddressManager) {\n        FRAUD_PROOF_WINDOW = _fraudProofWindow;\n        SEQUENCER_PUBLISH_WINDOW = _sequencerPublishWindow;\n    }\n\n    function setFraudProofWindow(uint256 window) external {\n        require(msg.sender == resolve(\"METIS_MANAGER\"), \"now allowed\");\n        FRAUD_PROOF_WINDOW = window;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Accesses the batch storage container.\n     * @return Reference to the batch storage container.\n     */\n    function batches() public view returns (IChainStorageContainer) {\n        return IChainStorageContainer(resolve(\"ChainStorageContainer-SCC-batches\"));\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalElements() external view returns (uint256 _totalElements) {\n        return getTotalElementsByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches) {\n        return getTotalBatchesByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getLastSequencerTimestamp() external view returns (uint256 _lastSequencerTimestamp) {\n        return getLastSequencerTimestampByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function appendStateBatch(bytes32[] memory _batch, uint256 _shouldStartAtElement) external {\n        //require (1==0, \"don't use\");\n        string memory proposer = string(\n            abi.encodePacked(Lib_Uint.uint2str(DEFAULT_CHAINID), \"_MVM_Proposer\")\n        );\n        appendStateBatchByChainId(DEFAULT_CHAINID, _batch, _shouldStartAtElement, proposer);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external {\n        deleteStateBatchByChainId(DEFAULT_CHAINID, _batchHeader);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function verifyStateCommitment(\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) external view returns (bool) {\n        return verifyStateCommitmentByChainId(DEFAULT_CHAINID, _element, _batchHeader, _proof);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)\n        public\n        view\n        returns (bool _inside)\n    {\n        (uint256 timestamp, ) = abi.decode(_batchHeader.extraData, (uint256, address));\n\n        require(timestamp != 0, \"Batch header timestamp cannot be zero\");\n        return (timestamp + FRAUD_PROOF_WINDOW) > block.timestamp;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Timestamp of the last batch submitted by the sequencer.\n     */\n    function _getBatchExtraData() internal view returns (uint40, uint40) {\n        // bytes27 extraData = batches().getGlobalMetadata();\n\n        // // solhint-disable max-line-length\n        // uint40 totalElements;\n        // uint40 lastSequencerTimestamp;\n        // assembly {\n        //     extraData := shr(40, extraData)\n        //     totalElements := and(\n        //         extraData,\n        //         0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n        //     )\n        //     lastSequencerTimestamp := shr(\n        //         40,\n        //         and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)\n        //     )\n        // }\n        // // solhint-enable max-line-length\n\n        // return (totalElements, lastSequencerTimestamp);\n\n        return _getBatchExtraDataByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _lastSequencerTimestamp Timestamp of the last batch submitted by the sequencer.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraData(uint40 _totalElements, uint40 _lastSequencerTimestamp)\n        internal\n        pure\n        returns (bytes27)\n    {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _lastSequencerTimestamp))\n            extraData := shl(40, extraData)\n        }\n\n        return extraData;\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _totalElements)\n    {\n        (uint40 totalElements, ) = _getBatchExtraDataByChainId(_chainId);\n        return uint256(totalElements);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _totalBatches)\n    {\n        return batches().lengthByChainId(_chainId);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getLastSequencerTimestampByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _lastSequencerTimestamp)\n    {\n        (, uint40 lastSequencerTimestamp) = _getBatchExtraDataByChainId(_chainId);\n        return uint256(lastSequencerTimestamp);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function appendStateBatchByChainId(\n        uint256 _chainId,\n        bytes32[] memory _batch,\n        uint256 _shouldStartAtElement,\n        string memory proposer\n    ) public override {\n        // Fail fast in to make sure our batch roots aren't accidentally made fraudulent by the\n        // publication of batches by some other user.\n        require(\n            _shouldStartAtElement == getTotalElementsByChainId(_chainId),\n            \"Actual batch start index does not match expected start index.\"\n        );\n\n        address proposerAddr = resolve(proposer);\n\n        // Proposers must have previously staked at the BondManager\n        require(\n            IBondManager(resolve(\"BondManager\")).isCollateralizedByChainId(\n                _chainId,\n                msg.sender,\n                proposerAddr\n            ),\n            \"Proposer does not have enough collateral posted\"\n        );\n\n        require(_batch.length > 0, \"Cannot submit an empty state batch.\");\n\n        require(\n            getTotalElementsByChainId(_chainId) + _batch.length <=\n                ICanonicalTransactionChain(resolve(\"CanonicalTransactionChain\"))\n                    .getTotalElementsByChainId(_chainId),\n            \"Number of state roots cannot exceed the number of canonical transactions.\"\n        );\n\n        // Pass the block's timestamp and the publisher of the data\n        // to be used in the fraud proofs\n        _appendBatchByChainId(\n            _chainId,\n            _batch,\n            abi.encode(block.timestamp, msg.sender),\n            proposerAddr\n        );\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function deleteStateBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) public override {\n        require(\n            msg.sender ==\n                resolve(\n                    string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_FraudVerifier\"))\n                ),\n            \"State batches can only be deleted by the MVM_FraudVerifier.\"\n        );\n\n        require(\n            insideFraudProofWindow(_batchHeader),\n            \"State batches can only be deleted within the fraud proof window.\"\n        );\n\n        _deleteBatchByChainId(_chainId, _batchHeader);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function verifyStateCommitmentByChainId(\n        uint256 _chainId,\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) public view override returns (bool) {\n        require(_isValidBatchHeaderByChainId(_chainId, _batchHeader), \"Invalid batch header.\");\n\n        require(\n            Lib_MerkleTree.verify(\n                _batchHeader.batchRoot,\n                _element,\n                _proof.index,\n                _proof.siblings,\n                _batchHeader.batchSize\n            ),\n            \"Invalid inclusion proof.\"\n        );\n\n        return true;\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function insideFraudProofWindowByChainId(\n        uint256,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) public view override returns (bool _inside) {\n        (uint256 timestamp, ) = abi.decode(_batchHeader.extraData, (uint256, address));\n\n        require(timestamp != 0, \"Batch header timestamp cannot be zero\");\n        return timestamp + FRAUD_PROOF_WINDOW > block.timestamp;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Timestamp of the last batch submitted by the sequencer.\n     */\n    function _getBatchExtraDataByChainId(uint256 _chainId) internal view returns (uint40, uint40) {\n        bytes27 extraData = batches().getGlobalMetadataByChainId(_chainId);\n\n        uint40 totalElements;\n        uint40 lastSequencerTimestamp;\n        assembly {\n            extraData := shr(40, extraData)\n            totalElements := and(\n                extraData,\n                0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n            )\n            lastSequencerTimestamp := shr(\n                40,\n                and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)\n            )\n        }\n\n        return (totalElements, lastSequencerTimestamp);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _lastSequencerTimestamp Timestamp of the last batch submitted by the sequencer.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraDataByChainId(uint40 _totalElements, uint40 _lastSequencerTimestamp)\n        internal\n        pure\n        returns (bytes27)\n    {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _lastSequencerTimestamp))\n            extraData := shl(40, extraData)\n        }\n\n        return extraData;\n    }\n\n    /**\n     * Appends a batch to the chain.\n     * @param _batch Elements within the batch.\n     * @param _extraData Any extra data to append to the batch.\n     */\n    function _appendBatchByChainId(\n        uint256 _chainId,\n        bytes32[] memory _batch,\n        bytes memory _extraData,\n        address\n    ) internal {\n        (uint40 totalElements, uint40 lastSequencerTimestamp) = _getBatchExtraDataByChainId(\n            _chainId\n        );\n\n        lastSequencerTimestamp = uint40(block.timestamp);\n\n        // if (msg.sender == proposer) {\n        //     lastSequencerTimestamp = uint40(block.timestamp);\n        // } else {\n        //     // We keep track of the last batch submitted by the sequencer so there's a window in\n        //     // which only the sequencer can publish state roots. A window like this just reduces\n        //     // the chance of \"system breaking\" state roots being published while we're still in\n        //     // testing mode. This window should be removed or significantly reduced in the future.\n        //     require(\n        //         lastSequencerTimestamp + SEQUENCER_PUBLISH_WINDOW < block.timestamp,\n        //         \"Cannot publish state roots within the sequencer publication window.\"\n        //     );\n        // }\n\n        // For efficiency reasons getMerkleRoot modifies the `_batch` argument in place\n        // while calculating the root hash therefore any arguments passed to it must not\n        // be used again afterwards\n        Lib_OVMCodec.ChainBatchHeader memory batchHeader = Lib_OVMCodec.ChainBatchHeader({\n            batchIndex: getTotalBatchesByChainId(_chainId),\n            batchRoot: Lib_MerkleTree.getMerkleRoot(_batch),\n            batchSize: _batch.length,\n            prevTotalElements: totalElements,\n            extraData: _extraData\n        });\n\n        emit StateBatchAppended(\n            _chainId,\n            batchHeader.batchIndex,\n            batchHeader.batchRoot,\n            batchHeader.batchSize,\n            batchHeader.prevTotalElements,\n            batchHeader.extraData\n        );\n\n        batches().pushByChainId(\n            _chainId,\n            Lib_OVMCodec.hashBatchHeader(batchHeader),\n            _makeBatchExtraDataByChainId(\n                uint40(batchHeader.prevTotalElements + batchHeader.batchSize),\n                lastSequencerTimestamp\n            )\n        );\n    }\n\n    /**\n     * Removes a batch and all subsequent batches from the chain.\n     * @param _batchHeader Header of the batch to remove.\n     */\n    function _deleteBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) internal {\n        require(\n            _batchHeader.batchIndex < batches().lengthByChainId(_chainId),\n            \"Invalid batch index.\"\n        );\n\n        require(_isValidBatchHeaderByChainId(_chainId, _batchHeader), \"Invalid batch header.\");\n\n        batches().deleteElementsAfterInclusiveByChainId(\n            _chainId,\n            _batchHeader.batchIndex,\n            _makeBatchExtraDataByChainId(uint40(_batchHeader.prevTotalElements), 0)\n        );\n\n        emit StateBatchDeleted(_chainId, _batchHeader.batchIndex, _batchHeader.batchRoot);\n    }\n\n    /**\n     * Checks that a batch header matches the stored hash for the given index.\n     * @param _batchHeader Batch header to validate.\n     * @return Whether or not the header matches the stored one.\n     */\n    function _isValidBatchHeaderByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) internal view returns (bool) {\n        return\n            Lib_OVMCodec.hashBatchHeader(_batchHeader) ==\n            batches().getByChainId(_chainId, _batchHeader.batchIndex);\n    }\n}\n"
    },
    "contracts/MVM/MVM_DiscountOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n/* Contract Imports */\n/* External Imports */\n\nimport { iMVM_DiscountOracle } from \"./iMVM_DiscountOracle.sol\";\nimport { Lib_AddressResolver } from \"../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_Uint } from \"../libraries/utils/Lib_Uint.sol\";\n\ncontract MVM_DiscountOracle is iMVM_DiscountOracle, Lib_AddressResolver {\n    // Current l2 gas price\n    uint256 public discount;\n    uint256 public minL2Gas;\n    mapping(address => bool) public xDomainWL;\n    mapping(uint256 => uint256) public l2ChainSeqGas;\n    bool public allowAllXDomainSenders;\n    string public constant CONFIG_OWNER_KEY = \"METIS_MANAGER\";\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    modifier onlyManager() {\n        require(\n            msg.sender == resolve(CONFIG_OWNER_KEY),\n            \"MVM_DiscountOracle: Function can only be called by the METIS_MANAGER.\"\n        );\n        _;\n    }\n\n    constructor(address _addressManager, uint256 _initialDiscount)\n        Lib_AddressResolver(_addressManager)\n    {\n        discount = _initialDiscount;\n        minL2Gas = 200_000;\n        allowAllXDomainSenders = false;\n    }\n\n    function getMinL2Gas() public view override returns (uint256) {\n        return minL2Gas;\n    }\n\n    function getDiscount() public view override returns (uint256) {\n        return discount;\n    }\n\n    function setDiscount(uint256 _discount) public override onlyManager {\n        discount = _discount;\n    }\n\n    function setMinL2Gas(uint256 _minL2Gas) public override onlyManager {\n        minL2Gas = _minL2Gas;\n    }\n\n    function setWhitelistedXDomainSender(address _sender, bool _isWhitelisted)\n        external\n        override\n        onlyManager\n    {\n        xDomainWL[_sender] = _isWhitelisted;\n    }\n\n    function isXDomainSenderAllowed(address _sender) public view override returns (bool) {\n        return (allowAllXDomainSenders || xDomainWL[_sender]);\n    }\n\n    function setAllowAllXDomainSenders(bool _allowAllXDomainSenders) public override onlyManager {\n        allowAllXDomainSenders = _allowAllXDomainSenders;\n    }\n\n    function processL2SeqGas(address sender, uint256 _chainId) public payable override {\n        require(isXDomainSenderAllowed(sender), \"sender is not whitelisted\");\n        require(_chainId > 0, \"incorrect chainId\");\n        l2ChainSeqGas[_chainId] += msg.value;\n    }\n\n    function withdrawToSeq(uint256 _amount, uint256 _chainId) public override onlyManager {\n        require(_amount > 0, \"incorrect amount\");\n        require(_amount <= address(this).balance, \"insufficient balance\");\n        require(_chainId > 0, \"incorrect chainId\");\n        require(_amount <= l2ChainSeqGas[_chainId], \"this chain sequencer gas is not enough\");\n        address _to = resolve(\n            string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Sequencer_Wrapper\"))\n        );\n        require(_to != address(0) && _to != address(this), \"unknown sequencer address\");\n        l2ChainSeqGas[_chainId] -= _amount;\n        (bool success, ) = _to.call{ value: _amount }(\"\");\n        require(success, \"transfer failed\");\n    }\n}\n"
    },
    "contracts/L1/verification/BondManager.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { IBondManager } from \"./IBondManager.sol\";\n\n/* Contract Imports */\nimport { Lib_AddressResolver } from \"../../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/**\n * @title BondManager\n * @dev This contract is, for now, a stub of the \"real\" BondManager that does nothing but\n * allow the \"OVM_Proposer\" to submit state root batches.\n *\n * Runtime target: EVM\n */\ncontract BondManager is IBondManager, Lib_AddressResolver {\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     */\n    constructor(address _libAddressManager) Lib_AddressResolver(_libAddressManager) {}\n\n    /**\n     * Checks whether a given address is properly collateralized and can perform actions within\n     * the system.\n     * @param _who Address to check.\n     * @return true if the address is properly collateralized, false otherwise.\n     */\n    function isCollateralized(address _who) public view returns (bool) {\n        // Only authenticate sequencer to submit state root batches.\n        return _who == resolve(\"OVM_Proposer\");\n    }\n\n    function isCollateralizedByChainId(\n        uint256 _chainId,\n        address _who,\n        address _prop\n    ) public view override returns (bool) {\n        require(_who == _prop, \"sender must the proposer!\");\n        require(\n            _prop ==\n                resolve(string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Proposer\"))),\n            \"Proposer does not match this chain.\"\n        );\n        return true;\n        //return bonds[_who].state == State.COLLATERALIZED;\n    }\n\n    // function registerSequencerByChainId(\n    //    uint256 _chainId,\n    //    address _sequencer,\n    //    address _proposer\n    //) public {\n    //}\n}\n"
    },
    "contracts/L1/rollup/CanonicalTransactionChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { AddressAliasHelper } from \"../../standards/AddressAliasHelper.sol\";\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\nimport { Lib_AddressResolver } from \"../../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/* Interface Imports */\nimport { ICanonicalTransactionChain } from \"./ICanonicalTransactionChain.sol\";\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title CanonicalTransactionChain\n * @dev The Canonical Transaction Chain (CTC) contract is an append-only log of transactions\n * which must be applied to the rollup state. It defines the ordering of rollup transactions by\n * writing them to the 'CTC:batches' instance of the Chain Storage Container.\n * The CTC only allows Proxy__OVM_L1CrossDomainMessenger address to 'enqueue' an L2 transaction, which will require that the\n * Sequencer will eventually append it to the rollup state.\n * The manager can add, delete and update the transactions data, update queue data,\n * when a fraud proof accepted in challege.\n *\n * Runtime target: EVM\n */\ncontract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressResolver {\n    /*************\n     * Constants *\n     *************/\n\n    // L2 tx gas-related\n    uint256 public constant MIN_ROLLUP_TX_GAS = 100000;\n    uint256 public constant MAX_ROLLUP_TX_SIZE = 50000;\n\n    // The approximate cost of calling the enqueue function\n    uint256 public enqueueGasCost;\n    // The ratio of the cost of L1 gas to the cost of L2 gas\n    uint256 public l2GasDiscountDivisor;\n    // The amount of L2 gas which can be forwarded to L2 without spam prevention via 'gas burn'.\n    // Calculated as the product of l2GasDiscountDivisor * enqueueGasCost.\n    // See comments in enqueue() for further detail.\n    uint256 public enqueueL2GasPrepaid;\n    //default l2 chain id\n    uint256 public constant DEFAULT_CHAINID = 1088;\n\n    // Encoding-related (all in bytes)\n    uint256 internal constant BATCH_CONTEXT_SIZE = 16;\n    // uint256 internal constant BATCH_CONTEXT_LENGTH_POS = 12;\n    uint256 internal constant BATCH_CONTEXT_START_POS = 15;\n    // uint256 internal constant TX_DATA_HEADER_SIZE = 3;\n    // uint256 internal constant BYTES_TILL_TX_DATA = 65;\n\n    /*************\n     * Variables *\n     *************/\n\n    uint256 public maxTransactionGasLimit;\n\n    /***************\n     * Queue State *\n     ***************/\n\n    mapping(uint256 => uint40) private _nextQueueIndex; // index of the first queue element not yet included\n    mapping(uint256 => Lib_OVMCodec.QueueElement[]) private queueElements;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor(\n        address _libAddressManager,\n        uint256 _maxTransactionGasLimit,\n        uint256 _l2GasDiscountDivisor,\n        uint256 _enqueueGasCost\n    ) Lib_AddressResolver(_libAddressManager) {\n        maxTransactionGasLimit = _maxTransactionGasLimit;\n        l2GasDiscountDivisor = _l2GasDiscountDivisor;\n        enqueueGasCost = _enqueueGasCost;\n        enqueueL2GasPrepaid = _l2GasDiscountDivisor * _enqueueGasCost;\n    }\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    /**\n     * Modifier to enforce that, if configured, only the Burn Admin may\n     * successfully call a method.\n     */\n    modifier onlyBurnAdmin() {\n        require(msg.sender == libAddressManager.owner(), \"Only callable by the Burn Admin.\");\n        _;\n    }\n\n    /*******************************\n     * Authorized Setter Functions *\n     *******************************/\n\n    /**\n     * Allows the Burn Admin to update the parameters which determine the amount of gas to burn.\n     * The value of enqueueL2GasPrepaid is immediately updated as well.\n     */\n    function setGasParams(uint256 _l2GasDiscountDivisor, uint256 _enqueueGasCost)\n        external\n        onlyBurnAdmin\n    {\n        enqueueGasCost = _enqueueGasCost;\n        l2GasDiscountDivisor = _l2GasDiscountDivisor;\n        // See the comment in enqueue() for the rationale behind this formula.\n        enqueueL2GasPrepaid = _l2GasDiscountDivisor * _enqueueGasCost;\n\n        emit L2GasParamsUpdated(l2GasDiscountDivisor, enqueueGasCost, enqueueL2GasPrepaid);\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Accesses the batch storage container.\n     * @return Reference to the batch storage container.\n     */\n    function batches() public view returns (IChainStorageContainer) {\n        return IChainStorageContainer(resolve(\"ChainStorageContainer-CTC-batches\"));\n    }\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElements() public view returns (uint256 _totalElements) {\n        (uint40 totalElements, , , ) = _getBatchExtraData();\n        return uint256(totalElements);\n    }\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches) {\n        return batches().length();\n    }\n\n    /**\n     * Returns the index of the next element to be enqueued.\n     * @return Index for the next queue element.\n     */\n    function getNextQueueIndex() external view returns (uint40) {\n        return _nextQueueIndex[DEFAULT_CHAINID];\n    }\n\n    /**\n     * Returns the timestamp of the last transaction.\n     * @return Timestamp for the last transaction.\n     */\n    function getLastTimestamp() external view returns (uint40) {\n        (, , uint40 lastTimestamp, ) = _getBatchExtraData();\n        return lastTimestamp;\n    }\n\n    /**\n     * Returns the blocknumber of the last transaction.\n     * @return Blocknumber for the last transaction.\n     */\n    function getLastBlockNumber() external view returns (uint40) {\n        (, , , uint40 lastBlockNumber) = _getBatchExtraData();\n        return lastBlockNumber;\n    }\n\n    /**\n     * Gets the queue element at a particular index.\n     * @param _index Index of the queue element to access.\n     * @return _element Queue element at the given index.\n     */\n    function getQueueElement(uint256 _index)\n        external\n        view\n        returns (Lib_OVMCodec.QueueElement memory _element)\n    {\n        return queueElements[DEFAULT_CHAINID][_index];\n    }\n\n    /**\n     * Get the number of queue elements which have not yet been included.\n     * @return Number of pending queue elements.\n     */\n    function getNumPendingQueueElements() external view returns (uint40) {\n        return uint40(queueElements[DEFAULT_CHAINID].length) - _nextQueueIndex[DEFAULT_CHAINID];\n    }\n\n    /**\n     * Retrieves the length of the queue, including\n     * both pending and canonical transactions.\n     * @return Length of the queue.\n     */\n    function getQueueLength() external view returns (uint40) {\n        return uint40(queueElements[DEFAULT_CHAINID].length);\n    }\n\n    /**\n     * Adds a transaction to the queue.\n     * @param _target Target L2 contract to send the transaction to.\n     * @param _gasLimit Gas limit for the enqueued L2 transaction.\n     * @param _data Transaction data.\n     */\n    function enqueue(\n        address _target,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) external {\n        enqueueByChainId(DEFAULT_CHAINID, _target, _gasLimit, _data);\n    }\n\n    /**\n     * Allows the sequencer to append a batch of transactions.\n     * @dev This function uses a custom encoding scheme for efficiency reasons.\n     * .param _shouldStartAtElement Specific batch we expect to start appending to.\n     * .param _totalElementsToAppend Total number of batch elements we expect to append.\n     * .param _contexts Array of batch contexts.\n     * .param _transactionDataFields Array of raw transaction data.\n     */\n    function appendSequencerBatch() external {\n        uint40 shouldStartAtElement;\n        uint24 totalElementsToAppend;\n        uint24 numContexts;\n        assembly {\n            shouldStartAtElement := shr(216, calldataload(4))\n            totalElementsToAppend := shr(232, calldataload(9))\n            numContexts := shr(232, calldataload(12))\n        }\n\n        require(\n            shouldStartAtElement == getTotalElements(),\n            \"Actual batch start index does not match expected start index.\"\n        );\n\n        require(\n            msg.sender == resolve(\"MVM_Sequencer\"),\n            \"Function can only be called by the Sequencer.\"\n        );\n\n        uint40 nextTransactionPtr = uint40(\n            BATCH_CONTEXT_START_POS + BATCH_CONTEXT_SIZE * numContexts\n        );\n\n        require(msg.data.length >= nextTransactionPtr, \"Not enough BatchContexts provided.\");\n\n        // Counter for number of sequencer transactions appended so far.\n        uint32 numSequencerTransactions = 0;\n\n        // Cache the _nextQueueIndex storage variable to a temporary stack variable.\n        // This is safe as long as nothing reads or writes to the storage variable\n        // until it is updated by the temp variable.\n        uint40 nextQueueIndex = _nextQueueIndex[DEFAULT_CHAINID];\n\n        BatchContext memory curContext;\n        for (uint32 i = 0; i < numContexts; i++) {\n            BatchContext memory nextContext = _getBatchContext(i);\n\n            // Now we can update our current context.\n            curContext = nextContext;\n\n            // Process sequencer transactions first.\n            numSequencerTransactions += uint32(curContext.numSequencedTransactions);\n\n            // Now process any subsequent queue transactions.\n            nextQueueIndex += uint40(curContext.numSubsequentQueueTransactions);\n        }\n\n        require(\n            nextQueueIndex <= queueElements[DEFAULT_CHAINID].length,\n            \"Attempted to append more elements than are available in the queue.\"\n        );\n\n        // Generate the required metadata that we need to append this batch\n        uint40 numQueuedTransactions = totalElementsToAppend - numSequencerTransactions;\n        uint40 blockTimestamp;\n        uint40 blockNumber;\n        if (curContext.numSubsequentQueueTransactions == 0) {\n            // The last element is a sequencer tx, therefore pull timestamp and block number from\n            // the last context.\n            blockTimestamp = uint40(curContext.timestamp);\n            blockNumber = uint40(curContext.blockNumber);\n        } else {\n            // The last element is a queue tx, therefore pull timestamp and block number from the\n            // queue element.\n            // curContext.numSubsequentQueueTransactions > 0 which means that we've processed at\n            // least one queue element. We increment nextQueueIndex after processing each queue\n            // element, so the index of the last element we processed is nextQueueIndex - 1.\n            Lib_OVMCodec.QueueElement memory lastElement = queueElements[DEFAULT_CHAINID][\n                nextQueueIndex - 1\n            ];\n\n            blockTimestamp = lastElement.timestamp;\n            blockNumber = lastElement.blockNumber;\n        }\n\n        // Cache the previous blockhash to ensure all transaction data can be retrieved efficiently.\n        _appendBatch(\n            blockhash(block.number - 1),\n            totalElementsToAppend,\n            numQueuedTransactions,\n            blockTimestamp,\n            blockNumber\n        );\n\n        emit SequencerBatchAppended(\n            DEFAULT_CHAINID,\n            nextQueueIndex - numQueuedTransactions,\n            numQueuedTransactions,\n            getTotalElements()\n        );\n\n        // Update the _nextQueueIndex storage variable.\n        _nextQueueIndex[DEFAULT_CHAINID] = nextQueueIndex;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Returns the BatchContext located at a particular index.\n     * @param _index The index of the BatchContext\n     * @return The BatchContext at the specified index.\n     */\n    function _getBatchContext(uint256 _index) internal pure returns (BatchContext memory) {\n        uint256 contextPtr = 15 + _index * BATCH_CONTEXT_SIZE;\n        uint256 numSequencedTransactions;\n        uint256 numSubsequentQueueTransactions;\n        uint256 ctxTimestamp;\n        uint256 ctxBlockNumber;\n\n        assembly {\n            numSequencedTransactions := shr(232, calldataload(contextPtr))\n            numSubsequentQueueTransactions := shr(232, calldataload(add(contextPtr, 3)))\n            ctxTimestamp := shr(216, calldataload(add(contextPtr, 6)))\n            ctxBlockNumber := shr(216, calldataload(add(contextPtr, 11)))\n        }\n\n        return\n            BatchContext({\n                numSequencedTransactions: numSequencedTransactions,\n                numSubsequentQueueTransactions: numSubsequentQueueTransactions,\n                timestamp: ctxTimestamp,\n                blockNumber: ctxBlockNumber\n            });\n    }\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Index of the next queue element.\n     */\n    function _getBatchExtraData()\n        internal\n        view\n        returns (\n            uint40,\n            uint40,\n            uint40,\n            uint40\n        )\n    {\n        bytes27 extraData = batches().getGlobalMetadata();\n\n        uint40 totalElements;\n        uint40 nextQueueIndex;\n        uint40 lastTimestamp;\n        uint40 lastBlockNumber;\n\n        // solhint-disable max-line-length\n        assembly {\n            extraData := shr(40, extraData)\n            totalElements := and(\n                extraData,\n                0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n            )\n            nextQueueIndex := shr(\n                40,\n                and(extraData, 0x00000000000000000000000000000000000000000000FFFFFFFFFF0000000000)\n            )\n            lastTimestamp := shr(\n                80,\n                and(extraData, 0x0000000000000000000000000000000000FFFFFFFFFF00000000000000000000)\n            )\n            lastBlockNumber := shr(\n                120,\n                and(extraData, 0x000000000000000000000000FFFFFFFFFF000000000000000000000000000000)\n            )\n        }\n        // solhint-enable max-line-length\n\n        return (totalElements, nextQueueIndex, lastTimestamp, lastBlockNumber);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _nextQueueIdx Index of the next queue element.\n     * @param _timestamp Timestamp for the last batch.\n     * @param _blockNumber Block number of the last batch.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraData(\n        uint40 _totalElements,\n        uint40 _nextQueueIdx,\n        uint40 _timestamp,\n        uint40 _blockNumber\n    ) internal pure returns (bytes27) {\n        // bytes27 extraData;\n        // assembly {\n        //     extraData := _totalElements\n        //     extraData := or(extraData, shl(40, _nextQueueIdx))\n        //     extraData := or(extraData, shl(80, _timestamp))\n        //     extraData := or(extraData, shl(120, _blockNumber))\n        //     extraData := shl(40, extraData)\n        // }\n\n        // return extraData;\n        return\n            _makeBatchExtraDataByChainId(_totalElements, _nextQueueIdx, _timestamp, _blockNumber);\n    }\n\n    /**\n     * Inserts a batch into the chain of batches.\n     * @param _transactionRoot Root of the transaction tree for this batch.\n     * @param _batchSize Number of elements in the batch.\n     * @param _numQueuedTransactions Number of queue transactions in the batch.\n     * @param _timestamp The latest batch timestamp.\n     * @param _blockNumber The latest batch blockNumber.\n     */\n    function _appendBatch(\n        bytes32 _transactionRoot,\n        uint256 _batchSize,\n        uint256 _numQueuedTransactions,\n        uint40 _timestamp,\n        uint40 _blockNumber\n    ) internal {\n        IChainStorageContainer batchesRef = batches();\n        (uint40 totalElements, uint40 nextQueueIndex, , ) = _getBatchExtraData();\n\n        Lib_OVMCodec.ChainBatchHeader memory header = Lib_OVMCodec.ChainBatchHeader({\n            batchIndex: batchesRef.length(),\n            batchRoot: _transactionRoot,\n            batchSize: _batchSize,\n            prevTotalElements: totalElements,\n            extraData: hex\"\"\n        });\n\n        emit TransactionBatchAppended(\n            DEFAULT_CHAINID,\n            header.batchIndex,\n            header.batchRoot,\n            header.batchSize,\n            header.prevTotalElements,\n            header.extraData\n        );\n\n        bytes32 batchHeaderHash = Lib_OVMCodec.hashBatchHeader(header);\n        bytes27 latestBatchContext = _makeBatchExtraData(\n            totalElements + uint40(header.batchSize),\n            nextQueueIndex + uint40(_numQueuedTransactions),\n            _timestamp,\n            _blockNumber\n        );\n\n        batchesRef.push(batchHeaderHash, latestBatchContext);\n    }\n\n    //added chain id for public function\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _totalElements)\n    {\n        (uint40 totalElements, , , ) = _getBatchExtraDataByChainId(_chainId);\n        return uint256(totalElements);\n    }\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        external\n        view\n        override\n        returns (uint256 _totalBatches)\n    {\n        return batches().lengthByChainId(_chainId);\n    }\n\n    /**\n     * Returns the index of the next element to be enqueued.\n     * @return Index for the next queue element.\n     */\n    function getNextQueueIndexByChainId(uint256 _chainId) external view override returns (uint40) {\n        (, uint40 nextQueueIndex, , ) = _getBatchExtraDataByChainId(_chainId);\n        return nextQueueIndex;\n    }\n\n    /**\n     * Returns the timestamp of the last transaction.\n     * @return Timestamp for the last transaction.\n     */\n    function getLastTimestampByChainId(uint256 _chainId) external view override returns (uint40) {\n        (, , uint40 lastTimestamp, ) = _getBatchExtraDataByChainId(_chainId);\n        return lastTimestamp;\n    }\n\n    /**\n     * Returns the blocknumber of the last transaction.\n     * @return Blocknumber for the last transaction.\n     */\n    function getLastBlockNumberByChainId(uint256 _chainId) external view override returns (uint40) {\n        (, , , uint40 lastBlockNumber) = _getBatchExtraDataByChainId(_chainId);\n        return lastBlockNumber;\n    }\n\n    /**\n     * Gets the queue element at a particular index.\n     * @param _index Index of the queue element to access.\n     * @return _element Queue element at the given index.\n     */\n    function getQueueElementByChainId(uint256 _chainId, uint256 _index)\n        external\n        view\n        override\n        returns (Lib_OVMCodec.QueueElement memory _element)\n    {\n        return queueElements[_chainId][_index];\n    }\n\n    /**\n     * Get the number of queue elements which have not yet been included.\n     * @return Number of pending queue elements.\n     */\n    function getNumPendingQueueElementsByChainId(uint256 _chainId)\n        external\n        view\n        override\n        returns (uint40)\n    {\n        return uint40(queueElements[_chainId].length) - _nextQueueIndex[_chainId];\n    }\n\n    /**\n     * Retrieves the length of the queue, including\n     * both pending and canonical transactions.\n     * @return Length of the queue.\n     */\n    function getQueueLengthByChainId(uint256 _chainId) external view override returns (uint40) {\n        return uint40(queueElements[_chainId].length);\n    }\n\n    /**\n     * Adds a transaction to the queue.\n     * @param _target Target L2 contract to send the transaction to.\n     * @param _gasLimit Gas limit for the enqueued L2 transaction.\n     * @param _data Transaction data.\n     */\n    function enqueueByChainId(\n        uint256 _chainId,\n        address _target,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) public override {\n        require(\n            msg.sender == resolve(\"Proxy__OVM_L1CrossDomainMessenger\"),\n            \"only the cross domain messenger can enqueue\"\n        );\n\n        require(\n            _data.length <= MAX_ROLLUP_TX_SIZE,\n            \"Transaction data size exceeds maximum for rollup transaction.\"\n        );\n\n        require(\n            _gasLimit <= maxTransactionGasLimit,\n            \"Transaction gas limit exceeds maximum for rollup transaction.\"\n        );\n\n        require(_gasLimit >= MIN_ROLLUP_TX_GAS, \"Transaction gas limit too low to enqueue.\");\n\n        // Transactions submitted to the queue lack a method for paying gas fees to the Sequencer.\n        // So we need to prevent spam attacks by ensuring that the cost of enqueueing a transaction\n        // from L1 to L2 is not underpriced. For transaction with a high L2 gas limit, we do this by\n        // burning some extra gas on L1. Of course there is also some intrinsic cost to enqueueing a\n        // transaction, so we want to make sure not to over-charge (by burning too much L1 gas).\n        // Therefore, we define 'enqueueL2GasPrepaid' as the L2 gas limit above which we must burn\n        // additional gas on L1. This threshold is the product of two inputs:\n        // 1. enqueueGasCost: the base cost of calling this function.\n        // 2. l2GasDiscountDivisor: the ratio between the cost of gas on L1 and L2. This is a\n        //    positive integer, meaning we assume L2 gas is always less costly.\n        // The calculation below for gasToConsume can be seen as converting the difference (between\n        // the specified L2 gas limit and the prepaid L2 gas limit) to an L1 gas amount.\n        if (_gasLimit > enqueueL2GasPrepaid) {\n            uint256 gasToConsume = (_gasLimit - enqueueL2GasPrepaid) / l2GasDiscountDivisor;\n            uint256 startingGas = gasleft();\n\n            // Although this check is not necessary (burn below will run out of gas if not true), it\n            // gives the user an explicit reason as to why the enqueue attempt failed.\n            require(startingGas > gasToConsume, \"Insufficient gas for L2 rate limiting burn.\");\n\n            uint256 i;\n            while (startingGas - gasleft() < gasToConsume) {\n                i++;\n            }\n        }\n\n        // Apply an aliasing unless msg.sender == tx.origin. This prevents an attack in which a\n        // contract on L1 has the same address as a contract on L2 but doesn't have the same code.\n        // We can safely ignore this for EOAs because they're guaranteed to have the same \"code\"\n        // (i.e. no code at all). This also makes it possible for users to interact with contracts\n        // on L2 even when the Sequencer is down.\n        address sender;\n        if (msg.sender == tx.origin) {\n            sender = msg.sender;\n        } else {\n            sender = AddressAliasHelper.applyL1ToL2Alias(msg.sender);\n        }\n\n        bytes32 transactionHash = keccak256(abi.encode(sender, _target, _gasLimit, _data));\n\n        queueElements[_chainId].push(\n            Lib_OVMCodec.QueueElement({\n                transactionHash: transactionHash,\n                timestamp: uint40(block.timestamp),\n                blockNumber: uint40(block.number)\n            })\n        );\n\n        uint256 queueIndex = queueElements[_chainId].length - 1;\n        emit TransactionEnqueued(\n            _chainId,\n            sender,\n            _target,\n            _gasLimit,\n            _data,\n            queueIndex,\n            block.timestamp\n        );\n    }\n\n    /**\n     * Allows the sequencer to append a batch of transactions.\n     * @dev This function uses a custom encoding scheme for efficiency reasons.\n     * .param _shouldStartAtElement Specific batch we expect to start appending to.\n     * .param _totalElementsToAppend Total number of batch elements we expect to append.\n     * .param _contexts Array of batch contexts.\n     * .param _transactionDataFields Array of raw transaction data.\n     */\n    function appendSequencerBatchByChainId() external override {\n        uint256 _chainId;\n        uint40 shouldStartAtElement;\n        uint24 totalElementsToAppend;\n        uint24 numContexts;\n        assembly {\n            _chainId := calldataload(4)\n            shouldStartAtElement := shr(216, calldataload(36))\n            totalElementsToAppend := shr(232, calldataload(41))\n            numContexts := shr(232, calldataload(44))\n        }\n\n        require(\n            shouldStartAtElement == getTotalElementsByChainId(_chainId),\n            \"Actual batch start index does not match expected start index.\"\n        );\n\n        require(\n            msg.sender ==\n                resolve(string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Sequencer\"))),\n            \"Function can only be called by the Sequencer.\"\n        );\n\n        require(numContexts > 0, \"Must provide at least one batch context.\");\n\n        require(totalElementsToAppend > 0, \"Must append at least one element.\");\n\n        uint40 nextTransactionPtr = uint40(\n            BATCH_CONTEXT_START_POS + BATCH_CONTEXT_SIZE * numContexts\n        );\n\n        require(msg.data.length >= nextTransactionPtr, \"Not enough BatchContexts provided.\");\n\n        // Cache the _nextQueueIndex storage variable to a temporary stack variable.\n        // This is safe as long as nothing reads or writes to the storage variable\n        // until it is updated by the temp variable.\n        uint40 nextQueueIndex = _nextQueueIndex[_chainId];\n\n        // Counter for number of sequencer transactions appended so far.\n        uint32 numSequencerTransactions = 0;\n\n        BatchContext memory curContext;\n        for (uint32 i = 0; i < numContexts; i++) {\n            BatchContext memory nextContext = _getBatchContextByChainId(0, i);\n\n            // Now we can update our current context.\n            curContext = nextContext;\n            // Process sequencer transactions first.\n            numSequencerTransactions += uint32(curContext.numSequencedTransactions);\n\n            // Now process any subsequent queue transactions.\n            nextQueueIndex += uint40(curContext.numSubsequentQueueTransactions);\n        }\n\n        require(\n            nextQueueIndex <= queueElements[_chainId].length,\n            \"Attempted to append more elements than are available in the queue.\"\n        );\n\n        // Generate the required metadata that we need to append this batch\n        uint40 numQueuedTransactions = totalElementsToAppend - numSequencerTransactions;\n        uint40 blockTimestamp;\n        uint40 blockNumber;\n        if (curContext.numSubsequentQueueTransactions == 0) {\n            // The last element is a sequencer tx, therefore pull timestamp and block number from\n            // the last context.\n            blockTimestamp = uint40(curContext.timestamp);\n            blockNumber = uint40(curContext.blockNumber);\n        } else {\n            // The last element is a queue tx, therefore pull timestamp and block number from the\n            // queue element.\n            // curContext.numSubsequentQueueTransactions > 0 which means that we've processed at\n            // least one queue element. We increment nextQueueIndex after processing each queue\n            // element, so the index of the last element we processed is nextQueueIndex - 1.\n            Lib_OVMCodec.QueueElement memory lastElement = queueElements[_chainId][\n                nextQueueIndex - 1\n            ];\n\n            blockTimestamp = lastElement.timestamp;\n            blockNumber = lastElement.blockNumber;\n        }\n\n        // Cache the previous blockhash to ensure all transaction data can be retrieved efficiently.\n        _appendBatchByChainId(\n            _chainId,\n            blockhash(block.number - 1),\n            totalElementsToAppend,\n            numQueuedTransactions,\n            blockTimestamp,\n            blockNumber\n        );\n\n        emit SequencerBatchAppended(\n            _chainId,\n            nextQueueIndex - numQueuedTransactions,\n            numQueuedTransactions,\n            getTotalElementsByChainId(_chainId)\n        );\n\n        // Update the _nextQueueIndex storage variable.\n        _nextQueueIndex[_chainId] = nextQueueIndex;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Returns the BatchContext located at a particular index.\n     * @param _index The index of the BatchContext\n     * @return The BatchContext at the specified index.\n     */\n    function _getBatchContextByChainId(uint256 _ptrStart, uint256 _index)\n        internal\n        pure\n        returns (BatchContext memory)\n    {\n        uint256 contextPtr = _ptrStart + 32 + 15 + _index * BATCH_CONTEXT_SIZE;\n        uint256 numSequencedTransactions;\n        uint256 numSubsequentQueueTransactions;\n        uint256 ctxTimestamp;\n        uint256 ctxBlockNumber;\n\n        assembly {\n            numSequencedTransactions := shr(232, calldataload(contextPtr))\n            numSubsequentQueueTransactions := shr(232, calldataload(add(contextPtr, 3)))\n            ctxTimestamp := shr(216, calldataload(add(contextPtr, 6)))\n            ctxBlockNumber := shr(216, calldataload(add(contextPtr, 11)))\n        }\n\n        return\n            BatchContext({\n                numSequencedTransactions: numSequencedTransactions,\n                numSubsequentQueueTransactions: numSubsequentQueueTransactions,\n                timestamp: ctxTimestamp,\n                blockNumber: ctxBlockNumber\n            });\n    }\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Index of the next queue element.\n     */\n    function _getBatchExtraDataByChainId(uint256 _chainId)\n        internal\n        view\n        returns (\n            uint40,\n            uint40,\n            uint40,\n            uint40\n        )\n    {\n        bytes27 extraData = batches().getGlobalMetadataByChainId(_chainId);\n\n        uint40 totalElements;\n        uint40 nextQueueIndex;\n        uint40 lastTimestamp;\n        uint40 lastBlockNumber;\n        assembly {\n            extraData := shr(40, extraData)\n            totalElements := and(\n                extraData,\n                0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n            )\n            nextQueueIndex := shr(\n                40,\n                and(extraData, 0x00000000000000000000000000000000000000000000FFFFFFFFFF0000000000)\n            )\n            lastTimestamp := shr(\n                80,\n                and(extraData, 0x0000000000000000000000000000000000FFFFFFFFFF00000000000000000000)\n            )\n            lastBlockNumber := shr(\n                120,\n                and(extraData, 0x000000000000000000000000FFFFFFFFFF000000000000000000000000000000)\n            )\n        }\n\n        return (totalElements, nextQueueIndex, lastTimestamp, lastBlockNumber);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _nextQueueIdx Index of the next queue element.\n     * @param _timestamp Timestamp for the last batch.\n     * @param _blockNumber Block number of the last batch.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraDataByChainId(\n        uint40 _totalElements,\n        uint40 _nextQueueIdx,\n        uint40 _timestamp,\n        uint40 _blockNumber\n    ) internal pure returns (bytes27) {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _nextQueueIdx))\n            extraData := or(extraData, shl(80, _timestamp))\n            extraData := or(extraData, shl(120, _blockNumber))\n            extraData := shl(40, extraData)\n        }\n\n        return extraData;\n    }\n\n    /**\n     * Inserts a batch into the chain of batches.\n     * @param _transactionRoot Root of the transaction tree for this batch.\n     * @param _batchSize Number of elements in the batch.\n     * @param _numQueuedTransactions Number of queue transactions in the batch.\n     * @param _timestamp The latest batch timestamp.\n     * @param _blockNumber The latest batch blockNumber.\n     */\n    function _appendBatchByChainId(\n        uint256 _chainId,\n        bytes32 _transactionRoot,\n        uint256 _batchSize,\n        uint256 _numQueuedTransactions,\n        uint40 _timestamp,\n        uint40 _blockNumber\n    ) internal {\n        IChainStorageContainer batchesRef = batches();\n        (uint40 totalElements, uint40 nextQueueIndex, , ) = _getBatchExtraDataByChainId(_chainId);\n\n        Lib_OVMCodec.ChainBatchHeader memory header = Lib_OVMCodec.ChainBatchHeader({\n            batchIndex: batchesRef.lengthByChainId(_chainId),\n            batchRoot: _transactionRoot,\n            batchSize: _batchSize,\n            prevTotalElements: totalElements,\n            extraData: hex\"\"\n        });\n\n        emit TransactionBatchAppended(\n            _chainId,\n            header.batchIndex,\n            header.batchRoot,\n            header.batchSize,\n            header.prevTotalElements,\n            header.extraData\n        );\n\n        bytes32 batchHeaderHash = Lib_OVMCodec.hashBatchHeader(header);\n        bytes27 latestBatchContext = _makeBatchExtraDataByChainId(\n            totalElements + uint40(header.batchSize),\n            nextQueueIndex + uint40(_numQueuedTransactions),\n            _timestamp,\n            _blockNumber\n        );\n\n        batchesRef.pushByChainId(_chainId, batchHeaderHash, latestBatchContext);\n    }\n\n    modifier onlyManager() {\n        require(\n            msg.sender == resolve(\"MVM_SuperManager\"),\n            \"ChainStorageContainer: Function can only be called by the owner.\"\n        );\n        _;\n    }\n\n    function pushQueueByChainId(uint256 _chainId, Lib_OVMCodec.QueueElement calldata _object)\n        external\n        override\n        onlyManager\n    {\n        queueElements[_chainId].push(_object);\n        emit QueuePushed(msg.sender, _chainId, _object);\n    }\n\n    function setQueueByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        Lib_OVMCodec.QueueElement calldata _object\n    ) external override onlyManager {\n        queueElements[_chainId][_index] = _object;\n        emit QueueSetted(msg.sender, _chainId, _index, _object);\n    }\n\n    function setBatchGlobalMetadataByChainId(uint256 _chainId, bytes27 _globalMetadata)\n        external\n        override\n        onlyManager\n    {\n        batches().setGlobalMetadataByChainId(_chainId, _globalMetadata);\n        emit BatchesGlobalMetadataSet(msg.sender, _chainId, _globalMetadata);\n    }\n\n    function getBatchGlobalMetadataByChainId(uint256 _chainId)\n        external\n        view\n        override\n        returns (bytes27)\n    {\n        return batches().getGlobalMetadataByChainId(_chainId);\n    }\n\n    function lengthBatchByChainId(uint256 _chainId) external view override returns (uint256) {\n        return batches().lengthByChainId(_chainId);\n    }\n\n    function pushBatchByChainId(\n        uint256 _chainId,\n        bytes32 _object,\n        bytes27 _globalMetadata\n    ) external override onlyManager {\n        batches().pushByChainId(_chainId, _object, _globalMetadata);\n        emit BatchPushed(msg.sender, _chainId, _object, _globalMetadata);\n    }\n\n    function setBatchByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes32 _object\n    ) external override onlyManager {\n        batches().setByChainId(_chainId, _index, _object);\n        emit BatchSetted(msg.sender, _chainId, _index, _object);\n    }\n\n    function getBatchByChainId(uint256 _chainId, uint256 _index)\n        external\n        view\n        override\n        returns (bytes32)\n    {\n        return batches().getByChainId(_chainId, _index);\n    }\n\n    function deleteBatchElementsAfterInclusiveByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    ) external override onlyManager {\n        batches().deleteElementsAfterInclusiveByChainId(_chainId, _index, _globalMetadata);\n        emit BatchElementDeleted(msg.sender, _chainId, _index, _globalMetadata);\n    }\n}\n"
    },
    "contracts/test-libraries/codec/TestLib_OVMCodec.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\n\n/**\n * @title TestLib_OVMCodec\n */\ncontract TestLib_OVMCodec {\n    function encodeTransaction(Lib_OVMCodec.Transaction memory _transaction)\n        public\n        pure\n        returns (bytes memory _encoded)\n    {\n        return Lib_OVMCodec.encodeTransaction(_transaction);\n    }\n\n    function hashTransaction(Lib_OVMCodec.Transaction memory _transaction)\n        public\n        pure\n        returns (bytes32 _hash)\n    {\n        return Lib_OVMCodec.hashTransaction(_transaction);\n    }\n}\n"
    },
    "contracts/test-libraries/rlp/TestLib_RLPReader.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_RLPReader } from \"../../libraries/rlp/Lib_RLPReader.sol\";\n\n/**\n * @title TestLib_RLPReader\n */\ncontract TestLib_RLPReader {\n    function readList(bytes memory _in) public pure returns (bytes[] memory) {\n        Lib_RLPReader.RLPItem[] memory decoded = Lib_RLPReader.readList(_in);\n        bytes[] memory out = new bytes[](decoded.length);\n        for (uint256 i = 0; i < out.length; i++) {\n            out[i] = Lib_RLPReader.readRawBytes(decoded[i]);\n        }\n        return out;\n    }\n\n    function readString(bytes memory _in) public pure returns (string memory) {\n        return Lib_RLPReader.readString(_in);\n    }\n\n    function readBytes(bytes memory _in) public pure returns (bytes memory) {\n        return Lib_RLPReader.readBytes(_in);\n    }\n\n    function readBytes32(bytes memory _in) public pure returns (bytes32) {\n        return Lib_RLPReader.readBytes32(_in);\n    }\n\n    function readUint256(bytes memory _in) public pure returns (uint256) {\n        return Lib_RLPReader.readUint256(_in);\n    }\n\n    function readBool(bytes memory _in) public pure returns (bool) {\n        return Lib_RLPReader.readBool(_in);\n    }\n\n    function readAddress(bytes memory _in) public pure returns (address) {\n        return Lib_RLPReader.readAddress(_in);\n    }\n}\n"
    },
    "contracts/L2/messaging/L2CrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { AddressAliasHelper } from \"../../standards/AddressAliasHelper.sol\";\nimport { Lib_CrossDomainUtils } from \"../../libraries/bridge/Lib_CrossDomainUtils.sol\";\nimport { Lib_DefaultValues } from \"../../libraries/constants/Lib_DefaultValues.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/* Interface Imports */\nimport { IL2CrossDomainMessenger } from \"./IL2CrossDomainMessenger.sol\";\nimport { iOVM_L2ToL1MessagePasser } from \"../predeploys/iOVM_L2ToL1MessagePasser.sol\";\nimport { OVM_DeployerWhitelist } from \"../predeploys/OVM_DeployerWhitelist.sol\";\n\n/**\n * @title L2CrossDomainMessenger\n * @dev The L2 Cross Domain Messenger contract sends messages from L2 to L1, and is the entry point\n * for L2 messages sent via the L1 Cross Domain Messenger.\n *\n */\ncontract L2CrossDomainMessenger is IL2CrossDomainMessenger {\n    /*************\n     * Variables *\n     *************/\n\n    mapping(bytes32 => bool) public relayedMessages;\n    mapping(bytes32 => bool) public successfulMessages;\n    mapping(bytes32 => bool) public sentMessages;\n    uint256 public messageNonce;\n    address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;\n    address public l1CrossDomainMessenger;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor(address _l1CrossDomainMessenger) {\n        l1CrossDomainMessenger = _l1CrossDomainMessenger;\n    }\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    modifier onlyWhitelisted() {\n        require(\n            OVM_DeployerWhitelist(Lib_PredeployAddresses.DEPLOYER_WHITELIST).isXDomainSenderAllowed(\n                    msg.sender\n                ),\n            // solhint-disable-next-line max-line-length\n            \"L2 to L1 messages are restricted to whitelisted senders.\"\n        );\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function xDomainMessageSender() public view returns (address) {\n        require(\n            xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER,\n            \"xDomainMessageSender is not set\"\n        );\n        return xDomainMsgSender;\n    }\n\n    /**\n     * Sends a cross domain message to the target messenger.\n     * @param _target Target contract address.\n     * @param _message Message to send to the target.\n     * @param _gasLimit Gas limit for the provided message.\n     */\n    function sendMessage(\n        address _target,\n        bytes memory _message,\n        uint32 _gasLimit\n    ) public payable onlyWhitelisted {\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            msg.sender,\n            _message,\n            messageNonce\n        );\n\n        sentMessages[keccak256(xDomainCalldata)] = true;\n\n        (bool sent, ) = Lib_PredeployAddresses.SEQUENCER_FEE_WALLET.call{ value: msg.value }(\"\");\n        require(sent, \"Failed to send bridge fee\");\n\n        // Actually send the message.\n        iOVM_L2ToL1MessagePasser(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER).passMessageToL1(\n            xDomainCalldata\n        );\n\n        // Emit an event before we bump the nonce or the nonce will be off by one.\n        emit SentMessage(_target, msg.sender, _message, messageNonce, _gasLimit, 1); //sending to l1 so chainid set to 1\n        messageNonce += 1;\n    }\n\n    /**\n     * Relays a cross domain message to a contract.\n     * @inheritdoc IL2CrossDomainMessenger\n     */\n    function relayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce\n    ) public {\n        require(\n            AddressAliasHelper.undoL1ToL2Alias(msg.sender) == l1CrossDomainMessenger,\n            \"Provided message could not be verified.\"\n        );\n\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            _sender,\n            _message,\n            _messageNonce\n        );\n\n        bytes32 xDomainCalldataHash = keccak256(xDomainCalldata);\n\n        require(\n            successfulMessages[xDomainCalldataHash] == false,\n            \"Provided message has already been received.\"\n        );\n\n        // Prevent calls to OVM_L2ToL1MessagePasser, which would enable\n        // an attacker to maliciously craft the _message to spoof\n        // a call from any L2 account.\n        if (_target == Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER) {\n            // Write to the successfulMessages mapping and return immediately.\n            successfulMessages[xDomainCalldataHash] = true;\n            return;\n        }\n\n        xDomainMsgSender = _sender;\n        (bool success, ) = _target.call(_message);\n        xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;\n\n        // Mark the message as received if the call was successful. Ensures that a message can be\n        // relayed multiple times in the case that the call reverted.\n        if (success == true) {\n            successfulMessages[xDomainCalldataHash] = true;\n            emit RelayedMessage(xDomainCalldataHash);\n        } else {\n            emit FailedRelayedMessage(xDomainCalldataHash);\n        }\n\n        // Store an identifier that can be used to prove that the given message was relayed by some\n        // user. Gives us an easy way to pay relayers for their work.\n        bytes32 relayId = keccak256(abi.encodePacked(xDomainCalldata, msg.sender, block.number));\n\n        relayedMessages[relayId] = true;\n    }\n\n    function sendMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        bytes calldata _message,\n        uint32 _gasLimit\n    ) public payable {}\n}\n"
    },
    "contracts/L2/messaging/IL2CrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { ICrossDomainMessenger } from \"../../libraries/bridge/ICrossDomainMessenger.sol\";\n\n/**\n * @title IL2CrossDomainMessenger\n */\ninterface IL2CrossDomainMessenger is ICrossDomainMessenger {\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Relays a cross domain message to a contract.\n     * @param _target Target contract address.\n     * @param _sender Message sender address.\n     * @param _message Message to send to the target.\n     * @param _messageNonce Nonce for the provided message.\n     */\n    function relayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce\n    ) external;\n}\n"
    },
    "contracts/L2/predeploys/iOVM_L2ToL1MessagePasser.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title iOVM_L2ToL1MessagePasser\n */\ninterface iOVM_L2ToL1MessagePasser {\n    /**********\n     * Events *\n     **********/\n\n    event L2ToL1Message(uint256 _nonce, address _sender, bytes _data);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function passMessageToL1(bytes calldata _message) external;\n}\n"
    },
    "contracts/L2/predeploys/OVM_DeployerWhitelist.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { iOVM_SequencerFeeVault } from \"./iOVM_SequencerFeeVault.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/**\n * @title OVM_DeployerWhitelist\n * @dev The Deployer Whitelist is a temporary predeploy used to provide additional safety during the\n * initial phases of our mainnet roll out. It is owned by the Optimism team, and defines accounts\n * which are allowed to deploy contracts on Layer2. The Execution Manager will only allow an\n * ovmCREATE or ovmCREATE2 operation to proceed if the deployer's address whitelisted.\n */\ncontract OVM_DeployerWhitelist {\n    /**********\n     * Events *\n     **********/\n\n    event OwnerChanged(address oldOwner, address newOwner);\n    event WhitelistStatusChanged(address deployer, bool whitelisted);\n    event WhitelistDisabled(address oldOwner);\n    mapping(address => bool) public xDomainWL;\n\n    /**********************\n     * Contract Constants *\n     **********************/\n\n    // WARNING: When owner is set to address(0), the whitelist is disabled.\n    address public owner;\n    mapping(address => bool) public whitelist;\n    bool public allowArbitraryDeployment;\n    bool public allowAllXDomainSenders;\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    /**\n     * Blocks functions to anyone except the contract owner.\n     */\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"Function can only be called by the owner of this contract.\");\n        _;\n    }\n\n    modifier onlyManager() {\n        require(\n            msg.sender ==\n                iOVM_SequencerFeeVault(Lib_PredeployAddresses.SEQUENCER_FEE_WALLET).getL2Manager(),\n            \"Function can only be called by the l2manager.\"\n        );\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Adds or removes an address from the deployment whitelist.\n     * @param _deployer Address to update permissions for.\n     * @param _isWhitelisted Whether or not the address is whitelisted.\n     */\n    function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external onlyOwner {\n        whitelist[_deployer] = _isWhitelisted;\n        allowArbitraryDeployment = false;\n        emit WhitelistStatusChanged(_deployer, _isWhitelisted);\n    }\n\n    function setWhitelistedXDomainSender(address _sender, bool _isWhitelisted) external onlyOwner {\n        xDomainWL[_sender] = _isWhitelisted;\n        allowAllXDomainSenders = false;\n        emit WhitelistStatusChanged(_sender, _isWhitelisted);\n    }\n\n    /**\n     * Updates the owner of this contract.\n     * @param _owner Address of the new owner.\n     */\n    function setOwner(address _owner) public onlyOwner {\n        emit OwnerChanged(owner, _owner);\n        owner = _owner;\n    }\n\n    /**\n     * Permanently enables arbitrary contract deployment and deletes the owner.\n     */\n    function enableArbitraryContractDeployment() external onlyOwner {\n        emit WhitelistDisabled(owner);\n        allowArbitraryDeployment = true;\n    }\n\n    function enableAllXDomainSenders() external onlyOwner {\n        emit WhitelistDisabled(owner);\n        allowAllXDomainSenders = true;\n    }\n\n    /**\n     * Checks whether an address is allowed to deploy contracts.\n     * @param _deployer Address to check.\n     * @return _allowed Whether or not the address can deploy contracts.\n     */\n    function isDeployerAllowed(address _deployer) external view returns (bool) {\n        return (owner == address(0) || allowArbitraryDeployment || whitelist[_deployer]);\n    }\n\n    function isXDomainSenderAllowed(address _sender) external view returns (bool) {\n        return (owner == address(0) || allowAllXDomainSenders == true || xDomainWL[_sender]);\n    }\n}\n"
    },
    "contracts/L2/predeploys/iOVM_SequencerFeeVault.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/* Contract Imports */\nimport { L2StandardBridge } from \"../messaging/L2StandardBridge.sol\";\nimport { CrossDomainEnabled } from \"../../libraries/bridge/CrossDomainEnabled.sol\";\n\n/**\n * @title OVM_SequencerFeeVault\n * @dev Simple holding contract for fees paid to the Sequencer. Likely to be replaced in the future\n * but \"good enough for now\".\n */\ninterface iOVM_SequencerFeeVault {\n    /*************\n     * Constants *\n     *************/\n\n    event ChainSwitch(address l1Wallet, address l2Manager);\n    event ConfigChange(bytes config);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function withdraw(uint256 amount) external payable;\n\n    function finalizeChainSwitch(address _FeeWallet, address _L2Manager) external;\n\n    function finalizeChainConfig(bytes calldata config) external;\n\n    function send(address payable to, uint256 amount) external;\n\n    function sendBatch(address payable[] calldata tos, uint256[] calldata amounts) external;\n\n    function getL2Manager() external view returns (address);\n}\n"
    },
    "contracts/L2/messaging/L2StandardBridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { IL1StandardBridge } from \"../../L1/messaging/IL1StandardBridge.sol\";\nimport { IL1ERC20Bridge } from \"../../L1/messaging/IL1ERC20Bridge.sol\";\nimport { IL2ERC20Bridge } from \"./IL2ERC20Bridge.sol\";\n\n/* Library Imports */\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { CrossDomainEnabled } from \"../../libraries/bridge/CrossDomainEnabled.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/* Contract Imports */\nimport { IL2StandardERC20 } from \"../../standards/IL2StandardERC20.sol\";\nimport { OVM_GasPriceOracle } from \"../predeploys/OVM_GasPriceOracle.sol\";\n\n/**\n * @title L2StandardBridge\n * @dev The L2 Standard bridge is a contract which works together with the L1 Standard bridge to\n * enable ETH and ERC20 transitions between L1 and L2.\n * This contract acts as a minter for new tokens when it hears about deposits into the L1 Standard\n * bridge.\n * This contract also acts as a burner of the tokens intended for withdrawal, informing the L1\n * bridge to release L1 funds.\n */\ncontract L2StandardBridge is IL2ERC20Bridge, CrossDomainEnabled {\n    /********************************\n     * External Contract References *\n     ********************************/\n\n    address public l1TokenBridge;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _l2CrossDomainMessenger Cross-domain messenger used by this contract.\n     * @param _l1TokenBridge Address of the L1 bridge deployed to the main chain.\n     */\n    constructor(address _l2CrossDomainMessenger, address _l1TokenBridge)\n        CrossDomainEnabled(_l2CrossDomainMessenger)\n    {\n        l1TokenBridge = _l1TokenBridge;\n    }\n\n    function getChainID() internal view returns (uint256) {\n        uint256 id;\n        assembly {\n            id := chainid()\n        }\n        return id;\n    }\n\n    /***************\n     * Withdrawing *\n     ***************/\n\n    /**\n     * @inheritdoc IL2ERC20Bridge\n     */\n    function withdraw(\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable virtual {\n        _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _l1Gas, _data);\n    }\n\n    function withdrawMetis(\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable virtual {\n        _initiateWithdrawal(\n            Lib_PredeployAddresses.MVM_COINBASE,\n            msg.sender,\n            msg.sender,\n            _amount,\n            _l1Gas,\n            _data\n        );\n    }\n\n    /**\n     * @inheritdoc IL2ERC20Bridge\n     */\n    function withdrawTo(\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable virtual {\n        _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _l1Gas, _data);\n    }\n\n    function withdrawMetisTo(\n        address _to,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable virtual {\n        _initiateWithdrawal(\n            Lib_PredeployAddresses.MVM_COINBASE,\n            msg.sender,\n            _to,\n            _amount,\n            _l1Gas,\n            _data\n        );\n    }\n\n    /**\n     * @dev Performs the logic for deposits by storing the token and informing the L2 token Gateway\n     * of the deposit.\n     * @param _l2Token Address of L2 token where withdrawal was initiated.\n     * @param _from Account to pull the deposit from on L2.\n     * @param _to Account to give the withdrawal to on L1.\n     * @param _amount Amount of the token to withdraw.\n     * param _l1Gas Unused, but included for potential forward compatibility considerations.\n     * @param _data Optional data to forward to L1. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateWithdrawal(\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) internal {\n        uint256 minL1Gas = OVM_GasPriceOracle(Lib_PredeployAddresses.OVM_GASPRICE_ORACLE)\n            .minErc20BridgeCost();\n\n        // require minimum gas unless, the metis manager is the sender\n        require(\n            msg.value >= minL1Gas || _from == Lib_PredeployAddresses.SEQUENCER_FEE_WALLET,\n            string(\n                abi.encodePacked(\n                    \"insufficient withdrawal fee supplied. need at least \",\n                    Lib_Uint.uint2str(minL1Gas)\n                )\n            )\n        );\n\n        // When a withdrawal is initiated, we burn the withdrawer's funds to prevent subsequent L2\n        // usage\n        IL2StandardERC20(_l2Token).burn(msg.sender, _amount);\n\n        // Construct calldata for l1TokenBridge.finalizeERC20Withdrawal(_to, _amount)\n        address l1Token = IL2StandardERC20(_l2Token).l1Token();\n        bytes memory message;\n\n        if (_l2Token == Lib_PredeployAddresses.OVM_ETH) {\n            message = abi.encodeWithSelector(\n                IL1StandardBridge.finalizeETHWithdrawalByChainId.selector,\n                getChainID(),\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        } else if (_l2Token == Lib_PredeployAddresses.MVM_COINBASE) {\n            message = abi.encodeWithSelector(\n                IL1ERC20Bridge.finalizeMetisWithdrawalByChainId.selector,\n                getChainID(),\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        } else {\n            message = abi.encodeWithSelector(\n                IL1ERC20Bridge.finalizeERC20WithdrawalByChainId.selector,\n                getChainID(),\n                l1Token,\n                _l2Token,\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        }\n\n        // Send message up to L1 bridge\n        sendCrossDomainMessage(\n            l1TokenBridge,\n            _l1Gas,\n            message,\n            msg.value // send all value as fees to cover relayer cost\n        );\n\n        emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data);\n    }\n\n    /************************************\n     * Cross-chain Function: Depositing *\n     ************************************/\n\n    /**\n     * @inheritdoc IL2ERC20Bridge\n     */\n    function finalizeDeposit(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external virtual onlyFromCrossDomainAccount(l1TokenBridge) {\n        // Check the target token is compliant and\n        // verify the deposited token on L1 matches the L2 deposited token representation here\n        if (\n            ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) &&\n            _l1Token == IL2StandardERC20(_l2Token).l1Token()\n        ) {\n            // When a deposit is finalized, we credit the account on L2 with the same amount of\n            // tokens.\n            IL2StandardERC20(_l2Token).mint(_to, _amount);\n            emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);\n        } else {\n            // disable because the mechanism is incompatible with the new xdomain fee structure.\n\n            // Either the L2 token which is being deposited-into disagrees about the correct address\n            // of its L1 token, or does not support the correct interface.\n            // This should only happen if there is a  malicious L2 token, or if a user somehow\n            // specified the wrong L2 token address to deposit into.\n            // In either case, we stop the process here and construct a withdrawal\n            // message so that users can get their funds out in some cases.\n            // There is no way to prevent malicious token contracts altogether, but this does limit\n            // user error and mitigate some forms of malicious contract behavior.\n            //bytes memory message = abi.encodeWithSelector(\n            //    iOVM_L1ERC20Bridge.finalizeERC20Withdrawal.selector,\n            //    _l1Token,\n            //    _l2Token,\n            //    _to,   // switched the _to and _from here to bounce back the deposit to the sender\n            //    _from,\n            //    _amount,\n            //    _data\n            //);\n\n            // Send message up to L1 bridge\n            //sendCrossDomainMessage(\n            //    l1TokenBridge,\n            //    0,\n            //    message,\n            //    0\n            //);\n            emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data);\n        }\n    }\n}\n"
    },
    "contracts/libraries/bridge/CrossDomainEnabled.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/* Interface Imports */\nimport { ICrossDomainMessenger } from \"./ICrossDomainMessenger.sol\";\n\n/**\n * @title CrossDomainEnabled\n * @dev Helper contract for contracts performing cross-domain communications\n *\n * Compiler used: defined by inheriting contract\n * Runtime target: defined by inheriting contract\n */\ncontract CrossDomainEnabled {\n    /*************\n     * Variables *\n     *************/\n\n    // Messenger contract used to send and recieve messages from the other domain.\n    address public messenger;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _messenger Address of the CrossDomainMessenger on the current layer.\n     */\n    constructor(address _messenger) {\n        messenger = _messenger;\n    }\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    /**\n     * Enforces that the modified function is only callable by a specific cross-domain account.\n     * @param _sourceDomainAccount The only account on the originating domain which is\n     *  authenticated to call this function.\n     */\n    modifier onlyFromCrossDomainAccount(address _sourceDomainAccount) {\n        require(\n            msg.sender == address(getCrossDomainMessenger()),\n            \"OVM_XCHAIN: messenger contract unauthenticated\"\n        );\n\n        require(\n            getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount,\n            \"OVM_XCHAIN: wrong sender of cross-domain message\"\n        );\n\n        _;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Gets the messenger, usually from storage. This function is exposed in case a child contract\n     * needs to override.\n     * @return The address of the cross-domain messenger contract which should be used.\n     */\n    function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {\n        return ICrossDomainMessenger(messenger);\n    }\n\n    /**q\n     * Sends a message to an account on another domain\n     * @param _crossDomainTarget The intended recipient on the destination domain\n     * @param _message The data to send to the target (usually calldata to a function with\n     *  `onlyFromCrossDomainAccount()`)\n     * @param _gasLimit The gasLimit for the receipt of the message on the target domain.\n     */\n    function sendCrossDomainMessage(\n        address _crossDomainTarget,\n        uint32 _gasLimit,\n        bytes memory _message,\n        uint256 fee\n    ) internal {\n        getCrossDomainMessenger().sendMessage{ value: fee }(\n            _crossDomainTarget,\n            _message,\n            _gasLimit\n        );\n    }\n\n    /**\n     * @notice Sends a message to an account on another domain\n     * @param _chainId L2 chain id.\n     * @param _crossDomainTarget The intended recipient on the destination domain\n     * @param _gasLimit The gasLimit for the receipt of the message on the target domain.\n     * @param _message The data to send to the target (usually calldata to a function with `onlyFromCrossDomainAccount()`)\n     */\n    function sendCrossDomainMessageViaChainId(\n        uint256 _chainId,\n        address _crossDomainTarget,\n        uint32 _gasLimit,\n        bytes memory _message,\n        uint256 fee\n    ) internal {\n        getCrossDomainMessenger().sendMessageViaChainId{ value: fee }(\n            _chainId,\n            _crossDomainTarget,\n            _message,\n            _gasLimit\n        );\n    }\n}\n"
    },
    "contracts/L1/messaging/IL1StandardBridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\nimport \"./IL1ERC20Bridge.sol\";\n\n/**\n * @title IL1StandardBridge\n */\ninterface IL1StandardBridge is IL1ERC20Bridge {\n    /**********\n     * Events *\n     **********/\n    event ETHDepositInitiated(\n        address indexed _from,\n        address indexed _to,\n        uint256 _amount,\n        bytes _data,\n        uint256 chainId\n    );\n\n    event ETHWithdrawalFinalized(\n        address indexed _from,\n        address indexed _to,\n        uint256 _amount,\n        bytes _data,\n        uint256 chainId\n    );\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @dev Deposit an amount of the ETH to the caller's balance on L2.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositETH(uint32 _l2Gas, bytes calldata _data) external payable;\n\n    /**\n     * @dev Deposit an amount of ETH to a recipient's balance on L2.\n     * @param _to L2 address to credit the withdrawal to.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositETHTo(\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable;\n\n    function depositETHByChainId(\n        uint256 _chainId,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable;\n\n    function depositETHToByChainId(\n        uint256 _chainId,\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable;\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n     * L1 ETH token. Since only the xDomainMessenger can call this function, it will never be called\n     * before the withdrawal is finalized.\n     * @param _from L2 address initiating the transfer.\n     * @param _to L1 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function finalizeETHWithdrawal(\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n\n    function finalizeETHWithdrawalByChainId(\n        uint256 _chainId,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n}\n"
    },
    "contracts/L1/messaging/IL1ERC20Bridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title IL1ERC20Bridge\n */\ninterface IL1ERC20Bridge {\n    /**********\n     * Events *\n     **********/\n\n    event ERC20DepositInitiated(\n        address indexed _l1Token,\n        address indexed _l2Token,\n        address indexed _from,\n        address _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    event ERC20WithdrawalFinalized(\n        address indexed _l1Token,\n        address indexed _l2Token,\n        address indexed _from,\n        address _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    event ERC20ChainID(uint256 _chainid);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @dev get the address of the corresponding L2 bridge contract.\n     * @return Address of the corresponding L2 bridge contract.\n     */\n    function l2TokenBridge() external returns (address);\n\n    /**\n     * @dev deposit an amount of the ERC20 to the caller's balance on L2.\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _amount Amount of the ERC20 to deposit\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositERC20(\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external;\n\n    /**\n     * @dev deposit an amount of ERC20 to a recipient's balance on L2.\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _to L2 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositERC20To(\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external;\n\n    /**\n     * @dev deposit an amount of the ERC20 to the caller's balance on L2.\n     * @param _chainid chainid\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _amount Amount of the ERC20 to deposit\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositERC20ByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable;\n\n    /**\n     * @dev deposit an amount of ERC20 to a recipient's balance on L2.\n     * @param _chainid chainid\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _to L2 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositERC20ToByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable;\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n     * L1 ERC20 token.\n     * This call will fail if the initialized withdrawal from L2 has not been finalized.\n     *\n     * @param _l1Token Address of L1 token to finalizeWithdrawal for.\n     * @param _l2Token Address of L2 token where withdrawal was initiated.\n     * @param _from L2 address initiating the transfer.\n     * @param _to L1 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _data Data provided by the sender on L2. This data is provided\n     *   solely as a convenience for external contracts. Aside from enforcing a maximum\n     *   length, these contracts provide no guarantees about its content.\n     */\n    function finalizeERC20Withdrawal(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n\n    /**\n     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n     * L1 ERC20 token.\n     * This call will fail if the initialized withdrawal from L2 has not been finalized.\n     *\n     * @param _chainid chainid\n     * @param _l1Token Address of L1 token to finalizeWithdrawal for.\n     * @param _l2Token Address of L2 token where withdrawal was initiated.\n     * @param _from L2 address initiating the transfer.\n     * @param _to L1 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _data Data provided by the sender on L2. This data is provided\n     *   solely as a convenience for external contracts. Aside from enforcing a maximum\n     *   length, these contracts provide no guarantees about its content.\n     */\n    function finalizeERC20WithdrawalByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n\n    /**\n     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n     * L1 ERC20 token.\n     * This call will fail if the initialized withdrawal from L2 has not been finalized.\n     *\n     * @param _chainid chainid\n     * @param _from L2 address initiating the transfer.\n     * @param _to L1 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _data Data provided by the sender on L2. This data is provided\n     *   solely as a convenience for external contracts. Aside from enforcing a maximum\n     *   length, these contracts provide no guarantees about its content.\n     */\n    function finalizeMetisWithdrawalByChainId(\n        uint256 _chainid,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n}\n"
    },
    "contracts/L2/messaging/IL2ERC20Bridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title IL2ERC20Bridge\n */\ninterface IL2ERC20Bridge {\n    /**********\n     * Events *\n     **********/\n\n    event WithdrawalInitiated(\n        address indexed _l1Token,\n        address indexed _l2Token,\n        address indexed _from,\n        address _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    event DepositFinalized(\n        address indexed _l1Token,\n        address indexed _l2Token,\n        address indexed _from,\n        address _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    event DepositFailed(\n        address indexed _l1Token,\n        address indexed _l2Token,\n        address indexed _from,\n        address _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @dev get the address of the corresponding L1 bridge contract.\n     * @return Address of the corresponding L1 bridge contract.\n     */\n    function l1TokenBridge() external returns (address);\n\n    /**\n     * @dev initiate a withdraw of some tokens to the caller's account on L1\n     * @param _l2Token Address of L2 token where withdrawal was initiated.\n     * @param _amount Amount of the token to withdraw.\n     * param _l1Gas Unused, but included for potential forward compatibility considerations.\n     * @param _data Optional data to forward to L1. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function withdraw(\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable;\n\n    /**\n     * @dev initiate a withdraw of some token to a recipient's account on L1.\n     * @param _l2Token Address of L2 token where withdrawal is initiated.\n     * @param _to L1 adress to credit the withdrawal to.\n     * @param _amount Amount of the token to withdraw.\n     * param _l1Gas Unused, but included for potential forward compatibility considerations.\n     * @param _data Optional data to forward to L1. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function withdrawTo(\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable;\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @dev Complete a deposit from L1 to L2, and credits funds to the recipient's balance of this\n     * L2 token. This call will fail if it did not originate from a corresponding deposit in\n     * L1StandardTokenBridge.\n     * @param _l1Token Address for the l1 token this is called with\n     * @param _l2Token Address for the l2 token this is called with\n     * @param _from Account to pull the deposit from on L2.\n     * @param _to Address to receive the withdrawal at\n     * @param _amount Amount of the token to withdraw\n     * @param _data Data provider by the sender on L1. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function finalizeDeposit(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n    // As per the EIP-165 spec, no interface should ever match 0xffffffff\n    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n    /**\n     * @dev Returns true if `account` supports the {IERC165} interface,\n     */\n    function supportsERC165(address account) internal view returns (bool) {\n        // Any contract that implements ERC165 must explicitly indicate support of\n        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n        return\n            _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n            !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n    }\n\n    /**\n     * @dev Returns true if `account` supports the interface defined by\n     * `interfaceId`. Support for {IERC165} itself is queried automatically.\n     *\n     * See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n        // query support of both ERC165 as per the spec and support of _interfaceId\n        return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n    }\n\n    /**\n     * @dev Returns a boolean array where each value corresponds to the\n     * interfaces passed in and whether they're supported or not. This allows\n     * you to batch check interfaces for a contract where your expectation\n     * is that some interfaces may not be supported.\n     *\n     * See {IERC165-supportsInterface}.\n     *\n     * _Available since v3.4._\n     */\n    function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n        internal\n        view\n        returns (bool[] memory)\n    {\n        // an array of booleans corresponding to interfaceIds and whether they're supported or not\n        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n        // query support of ERC165 itself\n        if (supportsERC165(account)) {\n            // query support of each interface in interfaceIds\n            for (uint256 i = 0; i < interfaceIds.length; i++) {\n                interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n            }\n        }\n\n        return interfaceIdsSupported;\n    }\n\n    /**\n     * @dev Returns true if `account` supports all the interfaces defined in\n     * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n     *\n     * Batch-querying can lead to gas savings by skipping repeated checks for\n     * {IERC165} support.\n     *\n     * See {IERC165-supportsInterface}.\n     */\n    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n        // query support of ERC165 itself\n        if (!supportsERC165(account)) {\n            return false;\n        }\n\n        // query support of each interface in _interfaceIds\n        for (uint256 i = 0; i < interfaceIds.length; i++) {\n            if (!_supportsERC165Interface(account, interfaceIds[i])) {\n                return false;\n            }\n        }\n\n        // all interfaces supported\n        return true;\n    }\n\n    /**\n     * @notice Query if a contract implements an interface, does not check ERC165 support\n     * @param account The address of the contract to query for support of an interface\n     * @param interfaceId The interface identifier, as specified in ERC-165\n     * @return true if the contract at account indicates support of the interface with\n     * identifier interfaceId, false otherwise\n     * @dev Assumes that account contains a contract that supports ERC165, otherwise\n     * the behavior of this method is undefined. This precondition can be checked\n     * with {supportsERC165}.\n     * Interface identification is specified in ERC-165.\n     */\n    function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n        bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n        (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n        if (result.length < 32) return false;\n        return success && abi.decode(result, (bool));\n    }\n}\n"
    },
    "contracts/standards/IL2StandardERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ninterface IL2StandardERC20 is IERC20, IERC165 {\n    function l1Token() external returns (address);\n\n    function mint(address _to, uint256 _amount) external;\n\n    function burn(address _from, uint256 _amount) external;\n\n    event Mint(address indexed _account, uint256 _amount);\n    event Burn(address indexed _account, uint256 _amount);\n}\n"
    },
    "contracts/L2/predeploys/OVM_GasPriceOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* External Imports */\n\nimport { iOVM_SequencerFeeVault } from \"./iOVM_SequencerFeeVault.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/**\n * @title OVM_GasPriceOracle\n * @dev This contract exposes the current l2 gas price, a measure of how congested the network\n * currently is. This measure is used by the Sequencer to determine what fee to charge for\n * transactions. When the system is more congested, the l2 gas price will increase and fees\n * will also increase as a result.\n *\n * All public variables are set while generating the initial L2 state. The\n * constructor doesn't run in practice as the L2 state generation script uses\n * the deployed bytecode instead of running the initcode.\n */\ncontract OVM_GasPriceOracle {\n    /*************\n     * Variables *\n     *************/\n    address public owner;\n    // Current L2 gas price\n    uint256 public gasPrice;\n    // Current L1 base fee\n    uint256 public l1BaseFee;\n    // Amortized cost of batch submission per transaction\n    uint256 public overhead;\n    // Value to scale the fee up by\n    uint256 public scalar;\n    // Number of decimals of the scalar\n    uint256 public decimals;\n\n    // minimum gas to bridge the asset back to l1\n    uint256 public minErc20BridgeCost;\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    /**\n     * Blocks functions to anyone except the contract owner.\n     */\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"Function can only be called by the owner of this contract.\");\n        _;\n    }\n\n    modifier onlyManager() {\n        require(\n            msg.sender ==\n                iOVM_SequencerFeeVault(Lib_PredeployAddresses.SEQUENCER_FEE_WALLET).getL2Manager(),\n            \"Function can only be called by the l2manager.\"\n        );\n        _;\n    }\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _owner Address that will initially own this contract.\n     */\n    constructor(address _owner) {\n        owner = _owner;\n    }\n\n    /**********\n     * Events *\n     **********/\n\n    event GasPriceUpdated(uint256);\n    event L1BaseFeeUpdated(uint256);\n    event OverheadUpdated(uint256);\n    event ScalarUpdated(uint256);\n    event DecimalsUpdated(uint256);\n    event MinErc20BridgeCostUpdated(uint256);\n    event OwnerChanged(address oldOwner, address newOwner);\n\n    /********************\n     * Public Functions *\n     ********************/\n    /**\n     * Updates the owner of this contract.\n     * @param _owner Address of the new owner.\n     */\n    function setOwner(address _owner) public onlyManager {\n        emit OwnerChanged(owner, _owner);\n        owner = _owner;\n    }\n\n    /**\n     * Allows the owner to modify the l2 gas price.\n     * @param _gasPrice New l2 gas price.\n     */\n    function setGasPrice(uint256 _gasPrice) public onlyOwner {\n        gasPrice = _gasPrice;\n        emit GasPriceUpdated(_gasPrice);\n    }\n\n    /**\n     * Allows the owner to modify the l1 bridge price.\n     * @param _minCost New l2 gas price.\n     */\n    function setMinErc20BridgeCost(uint256 _minCost) public onlyOwner {\n        minErc20BridgeCost = _minCost;\n        emit MinErc20BridgeCostUpdated(_minCost);\n    }\n\n    /**\n     * Allows the owner to modify the l1 base fee.\n     * @param _baseFee New l1 base fee\n     */\n    function setL1BaseFee(uint256 _baseFee) public onlyOwner {\n        if (l1BaseFee > 0) {\n            require(_baseFee < (l1BaseFee * 105) / 100, \"increase is capped at 5%\");\n        }\n        l1BaseFee = _baseFee;\n        emit L1BaseFeeUpdated(_baseFee);\n    }\n\n    /**\n     * Allows the owner to modify the overhead.\n     * @param _overhead New overhead\n     */\n    function setOverhead(uint256 _overhead) public onlyOwner {\n        if (overhead > 0) {\n            require(_overhead < (overhead * 105) / 100, \"increase is capped at 5%\");\n        }\n        overhead = _overhead;\n        emit OverheadUpdated(_overhead);\n    }\n\n    /**\n     * Allows the owner to modify the scalar.\n     * @param _scalar New scalar\n     */\n    function setScalar(uint256 _scalar) public onlyOwner {\n        if (scalar > 0) {\n            require(_scalar < (scalar * 105) / 100, \"increase is capped at 5%\");\n        }\n        scalar = _scalar;\n        emit ScalarUpdated(_scalar);\n    }\n\n    /**\n     * Allows the owner to modify the decimals.\n     * For maximum safety, this method should only be called when there is no active tx\n     * @param _decimals New decimals\n     */\n    function setDecimals(uint256 _decimals) public onlyOwner {\n        decimals = _decimals;\n        emit DecimalsUpdated(_decimals);\n    }\n\n    /**\n     * Computes the L1 portion of the fee\n     * based on the size of the RLP encoded tx\n     * and the current l1BaseFee\n     * @param _data Unsigned RLP encoded tx, 6 elements\n     * @return L1 fee that should be paid for the tx\n     */\n    function getL1Fee(bytes memory _data) public view returns (uint256) {\n        uint256 l1GasUsed = getL1GasUsed(_data);\n        uint256 l1Fee = l1GasUsed * l1BaseFee;\n        uint256 divisor = 10**decimals;\n        uint256 unscaled = l1Fee * scalar;\n        uint256 scaled = unscaled / divisor;\n        return scaled;\n    }\n\n    // solhint-disable max-line-length\n    /**\n     * Computes the amount of L1 gas used for a transaction\n     * The overhead represents the per batch gas overhead of\n     * posting both transaction and state roots to L1 given larger\n     * batch sizes.\n     * 4 gas for 0 byte\n     * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L33\n     * 16 gas for non zero byte\n     * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L87\n     * This will need to be updated if calldata gas prices change\n     * Account for the transaction being unsigned\n     * Padding is added to account for lack of signature on transaction\n     * 1 byte for RLP V prefix\n     * 1 byte for V\n     * 1 byte for RLP R prefix\n     * 32 bytes for R\n     * 1 byte for RLP S prefix\n     * 32 bytes for S\n     * Total: 68 bytes of padding\n     * @param _data Unsigned RLP encoded tx, 6 elements\n     * @return Amount of L1 gas used for a transaction\n     */\n    // solhint-enable max-line-length\n    function getL1GasUsed(bytes memory _data) public view returns (uint256) {\n        uint256 total = 0;\n        for (uint256 i = 0; i < _data.length; i++) {\n            if (_data[i] == 0) {\n                total += 4;\n            } else {\n                total += 16;\n            }\n        }\n        uint256 unsigned = total + overhead;\n        return unsigned + (68 * 16);\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
    },
    "contracts/MVM/MVM_L2ChainManagerOnL1.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\npragma experimental ABIEncoderV2;\n\n/* Library Imports */\nimport { CrossDomainEnabled } from \"../libraries/bridge/CrossDomainEnabled.sol\";\nimport { Lib_PredeployAddresses } from \"../libraries/constants/Lib_PredeployAddresses.sol\";\nimport { Lib_AddressManager } from \"../libraries/resolver/Lib_AddressManager.sol\";\nimport { iOVM_SequencerFeeVault } from \"../L2/predeploys/iOVM_SequencerFeeVault.sol\";\nimport { iMVM_L2ChainManagerOnL1 } from \"./iMVM_L2ChainManagerOnL1.sol\";\nimport { iMVM_DiscountOracle } from \"./iMVM_DiscountOracle.sol\";\n\n/* Interface Imports */\n\n/* External Imports */\n\n/**\n * @title MVM_L2ChainManagerOnL1\n * @dev if want support multi l2 chain on l1,it should add a manager to desc\n * how many l2 chain now ,and dispatch the l2 chain id to make it is unique.\n *\n * Compiler used: solc\n * Runtime target: EVM\n */\ncontract MVM_L2ChainManagerOnL1 is iMVM_L2ChainManagerOnL1, CrossDomainEnabled {\n    /*************\n     * Constants *\n     *************/\n    string public constant CONFIG_OWNER_KEY = \"METIS_MANAGER\";\n\n    /*************\n     * Variables *\n     *************/\n    address public addressmgr;\n    // chainid => sequencer\n    mapping(uint256 => address) squencers;\n\n    // chainid => configs (unused for now);\n    mapping(uint256 => bytes) configs;\n\n    /***************\n     * Constructor *\n     ***************/\n    // This contract lives behind a proxy, so the constructor parameters will go unused.\n    constructor() CrossDomainEnabled(address(0)) {}\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    modifier onlyManager() {\n        require(\n            msg.sender == Lib_AddressManager(addressmgr).getAddress(CONFIG_OWNER_KEY),\n            \"MVM_L2ChainManagerOnL1: Function can only be called by the METIS_MANAGER.\"\n        );\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n    function switchSequencer(\n        uint256 _chainId,\n        address wallet,\n        address manager\n    ) public payable onlyManager {\n        bytes memory message = abi.encodeWithSelector(\n            iOVM_SequencerFeeVault.finalizeChainSwitch.selector,\n            wallet,\n            manager\n        );\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            Lib_PredeployAddresses.SEQUENCER_FEE_WALLET,\n            uint32(1_000_000_000),\n            message,\n            msg.value\n        );\n\n        emit SwitchSeq(_chainId, wallet, manager);\n    }\n\n    function pushConfig(uint256 _chainId, bytes calldata _configs) public payable onlyManager {\n        bytes memory message = abi.encodeWithSelector(\n            iOVM_SequencerFeeVault.finalizeChainConfig.selector,\n            _configs\n        );\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            Lib_PredeployAddresses.SEQUENCER_FEE_WALLET,\n            uint32(1_000_000_000),\n            message,\n            msg.value\n        );\n\n        emit PushConfig(_chainId, _configs);\n    }\n}\n"
    },
    "contracts/MVM/iMVM_L2ChainManagerOnL1.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\npragma experimental ABIEncoderV2;\n\n/* Interface Imports */\n\n/* External Imports */\n\n/**\n * @title MVM_L2ChainManagerOnL1\n * @dev if want support multi l2 chain on l1,it should add a manager to desc\n * how many l2 chain now ,and dispatch the l2 chain id to make it is unique.\n *\n * Compiler used: solc\n * Runtime target: EVM\n */\ninterface iMVM_L2ChainManagerOnL1 {\n    event SwitchSeq(uint256 chainid, address wallet, address manager);\n    event PushConfig(uint256 chainid, bytes configs);\n\n    /********************\n     * Public Functions *\n     ********************/\n    function switchSequencer(\n        uint256 _chainId,\n        address wallet,\n        address manager\n    ) external payable;\n\n    function pushConfig(uint256 _chainId, bytes calldata configs) external payable;\n}\n"
    },
    "contracts/L2/predeploys/OVM_SequencerFeeVault.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/* Contract Imports */\nimport { L2StandardBridge } from \"../messaging/L2StandardBridge.sol\";\nimport { CrossDomainEnabled } from \"../../libraries/bridge/CrossDomainEnabled.sol\";\nimport { iOVM_SequencerFeeVault } from \"./iOVM_SequencerFeeVault.sol\";\nimport { iMVM_ChainConfig } from \"../../MVM/iMVM_ChainConfig.sol\";\n\n/**\n * @title OVM_SequencerFeeVault\n * @dev Simple holding contract for fees paid to the Sequencer. Likely to be replaced in the future\n * but \"good enough for now\".\n */\ncontract OVM_SequencerFeeVault is iOVM_SequencerFeeVault, CrossDomainEnabled {\n    /*************\n     * Variables *\n     *************/\n\n    // Address on L1 that will hold the fees once withdrawn. Dynamically initialized within l2geth.\n    address public l1FeeWallet;\n    address public l1Manager;\n    address public l2Manager;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _l1FeeWallet Initial address for the L1 wallet that will hold fees once withdrawn.\n     * Currently HAS NO EFFECT in production because l2geth will mutate this storage slot during\n     * the genesis block. This is ONLY for testing purposes.\n     */\n    constructor(\n        address _l2CrossDomainMessenger,\n        address _l1FeeWallet,\n        address _l1Manager\n    ) CrossDomainEnabled(_l2CrossDomainMessenger) {\n        l1FeeWallet = _l1FeeWallet;\n        l1Manager = _l1Manager;\n    }\n\n    modifier onlyManager() {\n        require(msg.sender == l2Manager, \"not allowed\");\n        _;\n    }\n\n    /************\n     * Fallback *\n     ************/\n\n    receive() external payable {}\n\n    // Fallback function is called when msg.data is not empty\n    fallback() external payable {}\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function withdraw(uint256 amount) public payable onlyManager {\n        require(address(this).balance >= amount, \"not enough balance to withraw\");\n\n        if (amount == 0) {\n            amount = address(this).balance;\n        }\n\n        L2StandardBridge(Lib_PredeployAddresses.L2_STANDARD_BRIDGE).withdrawTo{ value: msg.value }(\n            Lib_PredeployAddresses.MVM_COINBASE,\n            l1FeeWallet,\n            amount,\n            0,\n            bytes(\"\")\n        );\n    }\n\n    function finalizeChainSwitch(address _FeeWallet, address _L2Manager)\n        external\n        virtual\n        onlyFromCrossDomainAccount(l1Manager)\n    {\n        l1FeeWallet = _FeeWallet;\n        l2Manager = _L2Manager;\n        emit ChainSwitch(l1FeeWallet, l2Manager);\n    }\n\n    function finalizeChainConfig(bytes calldata values)\n        external\n        virtual\n        onlyFromCrossDomainAccount(l1Manager)\n    {\n        iMVM_ChainConfig(Lib_PredeployAddresses.MVM_CHAIN_CONFIG).setConfig(values);\n        emit ConfigChange(values);\n    }\n\n    function send(address payable to, uint256 amount) public onlyManager {\n        (bool sent, ) = to.call{ value: amount }(\"\");\n        require(sent, \"Failed to send metis\");\n    }\n\n    function sendBatch(address payable[] calldata tos, uint256[] calldata amounts)\n        public\n        onlyManager\n    {\n        require(tos.length == amounts.length, \"lengths of the parameters do not match\");\n        for (uint256 i = 0; i < tos.length; i++) {\n            send(tos[i], amounts[i]);\n        }\n    }\n\n    function getL2Manager() public view returns (address) {\n        return l2Manager;\n    }\n}\n"
    },
    "contracts/MVM/iMVM_ChainConfig.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Contract Imports */\n/* External Imports */\ninterface iMVM_ChainConfig {\n    event NewChainConfig(address sender, bytes32 key, bytes value);\n    event NewAccountConfig(address sender, address key, bytes value);\n\n    function setConfig(bytes32 key, bytes calldata values) external;\n\n    function setConfig(bytes calldata values) external;\n\n    function getConfig(bytes32 key) external view returns (bytes memory);\n\n    function getConfig() external view returns (bytes memory);\n}\n"
    },
    "contracts/MVM/MVM_ChainConfig.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\nimport { iMVM_ChainConfig } from \"./iMVM_ChainConfig.sol\";\n\n/* Contract Imports */\n/* External Imports */\ncontract MVM_ChainConfig is iMVM_ChainConfig {\n    bytes32 public constant DAC_NAME = keccak256(\"DAC_NAME\");\n    bytes32 public constant DAC_CHARTER = keccak256(\"DAC_CHARTER\");\n\n    // Current l2 gas price\n    mapping(bytes32 => bytes) public config;\n    mapping(address => bytes) public account_config;\n\n    constructor() {}\n\n    function setConfig(bytes32 key, bytes calldata values) public {\n        if (config[key].length == 0) {\n            config[key] = values;\n            emit NewChainConfig(msg.sender, key, values);\n        }\n    }\n\n    function setConfig(bytes calldata values) public {\n        account_config[msg.sender] = values;\n        emit NewAccountConfig(msg.sender, msg.sender, values);\n    }\n\n    function getConfig(bytes32 key) public view returns (bytes memory) {\n        return config[key];\n    }\n\n    function getConfig() public view returns (bytes memory) {\n        return account_config[msg.sender];\n    }\n}\n"
    },
    "contracts/standards/L2StandardERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./IL2StandardERC20.sol\";\n\ncontract L2StandardERC20 is IL2StandardERC20, ERC20 {\n    address public l1Token;\n    address public l2Bridge;\n\n    /**\n     * @param _l2Bridge Address of the L2 standard bridge.\n     * @param _l1Token Address of the corresponding L1 token.\n     * @param _name ERC20 name.\n     * @param _symbol ERC20 symbol.\n     */\n    constructor(\n        address _l2Bridge,\n        address _l1Token,\n        string memory _name,\n        string memory _symbol\n    ) ERC20(_name, _symbol) {\n        l1Token = _l1Token;\n        l2Bridge = _l2Bridge;\n    }\n\n    modifier onlyL2Bridge() {\n        require(msg.sender == l2Bridge, \"Only L2 Bridge can mint and burn\");\n        _;\n    }\n\n    function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {\n        bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n        bytes4 secondSupportedInterface = IL2StandardERC20.l1Token.selector ^\n            IL2StandardERC20.mint.selector ^\n            IL2StandardERC20.burn.selector;\n        return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n    }\n\n    function mint(address _to, uint256 _amount) public virtual onlyL2Bridge {\n        _mint(_to, _amount);\n\n        emit Mint(_to, _amount);\n    }\n\n    function burn(address _from, uint256 _amount) public virtual onlyL2Bridge {\n        _burn(_from, _amount);\n\n        emit Burn(_from, _amount);\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * The default value of {decimals} is 18. To select a different value for\n     * {decimals} you should overload it.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\n     * overridden;\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `recipient` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n        _transfer(_msgSender(), recipient, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        _approve(_msgSender(), spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * Requirements:\n     *\n     * - `sender` and `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``sender``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) public virtual override returns (bool) {\n        _transfer(sender, recipient, amount);\n\n        uint256 currentAllowance = _allowances[sender][_msgSender()];\n        require(currentAllowance >= amount, \"ERC20: transfer amount exceeds allowance\");\n        unchecked {\n            _approve(sender, _msgSender(), currentAllowance - amount);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        uint256 currentAllowance = _allowances[_msgSender()][spender];\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `sender` to `recipient`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `sender` cannot be the zero address.\n     * - `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     */\n    function _transfer(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) internal virtual {\n        require(sender != address(0), \"ERC20: transfer from the zero address\");\n        require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(sender, recipient, amount);\n\n        uint256 senderBalance = _balances[sender];\n        require(senderBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[sender] = senderBalance - amount;\n        }\n        _balances[recipient] += amount;\n\n        emit Transfer(sender, recipient, amount);\n\n        _afterTokenTransfer(sender, recipient, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        _balances[account] += amount;\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n        }\n        _totalSupply -= amount;\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
    },
    "contracts/MVM/MVM_Coinbase.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_PredeployAddresses } from \"../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/* Contract Imports */\nimport { L2StandardERC20 } from \"../standards/L2StandardERC20.sol\";\n\n/**\n * @title OVM_ETH\n * @dev The ETH predeploy provides an ERC20 interface for ETH deposited to Layer 2. Note that\n * unlike on Layer 1, Layer 2 accounts do not have a balance field.\n *\n * Runtime target: OVM\n */\ncontract MVM_Coinbase is L2StandardERC20 {\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor()\n        L2StandardERC20(\n            Lib_PredeployAddresses.L2_STANDARD_BRIDGE,\n            address(0),\n            \"Metis Token\",\n            \"Metis\"\n        )\n    {}\n}\n"
    },
    "contracts/MVM/MVM_GasOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n/* Contract Imports */\n/* External Imports */\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { MVM_Coinbase } from \"./MVM_Coinbase.sol\";\nimport { Lib_PredeployAddresses } from \"../libraries/constants/Lib_PredeployAddresses.sol\";\n\ncontract MVM_GasOracle is Ownable {\n    // Current l2 gas price\n    uint256 public gasPrice;\n    uint256 public minL1GasLimit;\n\n    constructor(address _owner, uint256 _initialGasPrice) Ownable() {\n        setGasPrice(_initialGasPrice);\n        transferOwnership(_owner);\n    }\n\n    function setGasPrice(uint256 _gasPrice) public onlyOwner {\n        gasPrice = _gasPrice;\n    }\n\n    function setMinL1GasLimit(uint256 gas) public onlyOwner {\n        minL1GasLimit = gas;\n    }\n\n    //for compatibility\n    function setPrice(uint256 _gasPrice) public onlyOwner {\n        gasPrice = _gasPrice;\n    }\n\n    function transferSetter(address newsetter) public onlyOwner {\n        transferOwnership(newsetter);\n    }\n\n    function transferTo(address target, uint256 amount) public onlyOwner {\n        // Transfer fee to relayer.\n        require(\n            MVM_Coinbase(Lib_PredeployAddresses.MVM_COINBASE).transfer(target, amount),\n            \"transfer failed.\"\n        );\n    }\n}\n"
    },
    "contracts/L1/messaging/L1StandardBridgeLocal.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { IL1StandardBridge } from \"./IL1StandardBridge.sol\";\nimport { IL1ERC20Bridge } from \"./IL1ERC20Bridge.sol\";\nimport { IL2ERC20Bridge } from \"../../L2/messaging/IL2ERC20Bridge.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/* Library Imports */\nimport { CrossDomainEnabled } from \"../../libraries/bridge/CrossDomainEnabled.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { iMVM_DiscountOracle } from \"../../MVM/iMVM_DiscountOracle.sol\";\nimport { Lib_AddressManager } from \"../../libraries/resolver/Lib_AddressManager.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/**\n * @title L1StandardBridgeLocal\n * @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard\n * tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits\n * and listening to it for newly finalized withdrawals.\n *\n * Runtime target: EVM\n */\ncontract L1StandardBridgeLocal is IL1StandardBridge, CrossDomainEnabled {\n    using SafeERC20 for IERC20;\n\n    /********************************\n     * External Contract References *\n     ********************************/\n\n    address public l2TokenBridge;\n    address public metis;\n    address public addressmgr;\n\n    // Maps L1 token to chainid to L2 token to balance of the L1 token deposited\n    mapping(address => mapping(uint256 => mapping(address => uint256))) public deposits;\n\n    uint256 public constant DEFAULT_CHAINID = 1088;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    // This contract lives behind a proxy, so the constructor parameters will go unused.\n    constructor() CrossDomainEnabled(address(0)) {}\n\n    /******************\n     * Initialization *\n     ******************/\n\n    /**\n     * @param _l1messenger L1 Messenger address being used for cross-chain communications.\n     * @param _l2TokenBridge L2 standard bridge address.\n     */\n    function initialize(\n        address _l1messenger,\n        address _l2TokenBridge,\n        address _metis,\n        address _addressmgr\n    ) public {\n        require(messenger == address(0), \"Contract has already been initialized.\");\n        messenger = _l1messenger;\n        l2TokenBridge = _l2TokenBridge;\n        metis = _metis;\n        addressmgr = _addressmgr;\n    }\n\n    /**************\n     * Depositing *\n     **************/\n\n    /** @dev Modifier requiring sender to be EOA.  This check could be bypassed by a malicious\n     *  contract via initcode, but it takes care of the user error we want to avoid.\n     */\n    modifier onlyEOA() {\n        // Used to stop deposits from contracts (avoid accidentally lost tokens)\n        require(!Address.isContract(msg.sender), \"Account not EOA\");\n        _;\n    }\n\n    /**\n     * @dev do not accept no data call\n     */\n    receive() external payable onlyEOA {\n        require(false, \"do not send eth directly\");\n    }\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA {\n        _initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data);\n    }\n\n    function depositETHByChainId(\n        uint256 _chainId,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable override onlyEOA {\n        _initiateETHDepositByChainId(_chainId, msg.sender, msg.sender, _l2Gas, _data);\n    }\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function depositETHTo(\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable {\n        _initiateETHDeposit(msg.sender, _to, _l2Gas, _data);\n    }\n\n    function depositETHToByChainId(\n        uint256 _chainId,\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable override {\n        _initiateETHDepositByChainId(_chainId, msg.sender, _to, _l2Gas, _data);\n    }\n\n    /**\n     * @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of\n     * the deposit.\n     * @param _from Account to pull the deposit from on L1.\n     * @param _to Account to give the deposit to on L2.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateETHDeposit(\n        address _from,\n        address _to,\n        uint32 _l2Gas,\n        bytes memory _data\n    ) internal {\n        _initiateETHDepositByChainId(DEFAULT_CHAINID, _from, _to, _l2Gas, _data);\n    }\n\n    function _initiateETHDepositByChainId(\n        uint256 _chainId,\n        address _from,\n        address _to,\n        uint32 _l2Gas,\n        bytes memory _data\n    ) internal {\n        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(\n            Lib_AddressManager(addressmgr).getAddress(\"MVM_DiscountOracle\")\n        );\n        uint32 mingas = uint32(oracle.getMinL2Gas());\n        if (_l2Gas < mingas) {\n            _l2Gas = mingas;\n        }\n        uint256 fee = _l2Gas * oracle.getDiscount();\n\n        require(\n            fee <= msg.value,\n            string(\n                abi.encodePacked(\n                    \"insufficient fee supplied. send at least \",\n                    Lib_Uint.uint2str(fee)\n                )\n            )\n        );\n        // Construct calldata for finalizeDeposit call\n        bytes memory message = abi.encodeWithSelector(\n            IL2ERC20Bridge.finalizeDeposit.selector,\n            address(0),\n            Lib_PredeployAddresses.MVM_COINBASE, //MVM: only for local dev environment for easier funding\n            _from,\n            _to,\n            msg.value - fee,\n            _data\n        );\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            l2TokenBridge,\n            _l2Gas,\n            message,\n            fee // only send the supplied fees over (obviously)\n        );\n\n        emit ETHDepositInitiated(_from, _to, msg.value, _data, _chainId);\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function depositERC20(\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external virtual onlyEOA {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            msg.sender,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function depositERC20To(\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external virtual {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    function depositERC20ByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable virtual override onlyEOA {\n        _initiateERC20DepositByChainId(\n            _chainid,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            msg.sender,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    function depositERC20ToByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable virtual override {\n        _initiateERC20DepositByChainId(\n            _chainid,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @dev Performs the logic for deposits by informing the L2 Deposited Token\n     * contract of the deposit and calling a handler to lock the L1 funds. (e.g. transferFrom)\n     *\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _from Account to pull the deposit from on L1\n     * @param _to Account to give the deposit to on L2\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateERC20Deposit(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) internal {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            _from,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    function _initiateERC20DepositByChainId(\n        uint256 _chainId,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) internal {\n        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(\n            Lib_AddressManager(addressmgr).getAddress(\"MVM_DiscountOracle\")\n        );\n\n        // stack too deep. so no more local variables\n        if (_l2Gas < uint32(oracle.getMinL2Gas())) {\n            _l2Gas = uint32(oracle.getMinL2Gas());\n        }\n\n        require(\n            _l2Gas * oracle.getDiscount() <= msg.value,\n            string(\n                abi.encodePacked(\n                    \"insufficient fee supplied. send at least \",\n                    Lib_Uint.uint2str(_l2Gas * oracle.getDiscount())\n                )\n            )\n        );\n\n        // When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future\n        // withdrawals. safeTransferFrom also checks if the contract has code, so this will fail if\n        // _from is an EOA or address(0).\n        IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);\n\n        bytes memory message;\n        if (_l1Token == metis) {\n            // Construct calldata for finalizeDeposit call\n            _l2Token = Lib_PredeployAddresses.MVM_COINBASE;\n            message = abi.encodeWithSelector(\n                IL2ERC20Bridge.finalizeDeposit.selector,\n                address(0),\n                Lib_PredeployAddresses.MVM_COINBASE,\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        } else {\n            // Construct calldata for finalizeDeposit call\n            message = abi.encodeWithSelector(\n                IL2ERC20Bridge.finalizeDeposit.selector,\n                _l1Token,\n                _l2Token,\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        }\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            l2TokenBridge,\n            _l2Gas,\n            message,\n            msg.value //send all values as fees to cover l2 tx cost\n        );\n\n        deposits[_l1Token][_chainId][_l2Token] = deposits[_l1Token][_chainId][_l2Token] + (_amount);\n\n        emit ERC20ChainID(_chainId);\n        emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function finalizeETHWithdrawal(\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external onlyFromCrossDomainAccount(l2TokenBridge) {\n        (bool success, ) = _to.call{ value: _amount }(new bytes(0));\n        require(success, \"TransferHelper::safeTransferETH: ETH transfer failed\");\n\n        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, DEFAULT_CHAINID);\n    }\n\n    function finalizeETHWithdrawalByChainId(\n        uint256 _chainid,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        (bool success, ) = _to.call{ value: _amount }(new bytes(0));\n        require(success, \"TransferHelper::safeTransferETH: ETH transfer failed\");\n\n        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, _chainid);\n    }\n\n    function finalizeMetisWithdrawalByChainId(\n        uint256 _chainid,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        // _finalizeERC20WithdrawalByChainId(\n        //     _chainid,\n        //     metis,\n        //     Lib_PredeployAddresses.MVM_COINBASE,\n        //     _from,\n        //     _to,\n        //     _amount,\n        //     _data\n        // );\n\n        //MVM: only for local dev environment for easier funding\n        (bool success, ) = _to.call{ value: _amount }(new bytes(0));\n        require(success, \"TransferHelper::safeTransferETH: ETH transfer failed\");\n\n        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, _chainid);\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function finalizeERC20Withdrawal(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external onlyFromCrossDomainAccount(l2TokenBridge) {\n        _finalizeERC20WithdrawalByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            _from,\n            _to,\n            _amount,\n            _data\n        );\n    }\n\n    function finalizeERC20WithdrawalByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        _finalizeERC20WithdrawalByChainId(_chainid, _l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    function _finalizeERC20WithdrawalByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) internal {\n        deposits[_l1Token][_chainid][_l2Token] = deposits[_l1Token][_chainid][_l2Token] - _amount;\n\n        // When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer\n        IERC20(_l1Token).safeTransfer(_to, _amount);\n\n        emit ERC20ChainID(_chainid);\n        emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    /*****************************\n     * Temporary - Migrating ETH *\n     *****************************/\n\n    /**\n     * @dev Adds ETH balance to the account. This is meant to allow for ETH\n     * to be migrated from an old gateway to a new gateway.\n     * NOTE: This is left for one upgrade only so we are able to receive the migrated ETH from the\n     * old contract\n     */\n    function donateETH() external payable {}\n}\n"
    },
    "@openzeppelin/contracts/utils/Address.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        assembly {\n            size := extcodesize(account)\n        }\n        return size > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
    },
    "contracts/libraries/resolver/Lib_ResolvedDelegateProxy.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_AddressManager } from \"./Lib_AddressManager.sol\";\n\n/**\n * @title Lib_ResolvedDelegateProxy\n */\ncontract Lib_ResolvedDelegateProxy {\n    /*************\n     * Variables *\n     *************/\n\n    // Using mappings to store fields to avoid overwriting storage slots in the\n    // implementation contract. For example, instead of storing these fields at\n    // storage slot `0` & `1`, they are stored at `keccak256(key + slot)`.\n    // See: https://solidity.readthedocs.io/en/v0.7.0/internals/layout_in_storage.html\n    // NOTE: Do not use this code in your own contract system.\n    //      There is a known flaw in this contract, and we will remove it from the repository\n    //      in the near future. Due to the very limited way that we are using it, this flaw is\n    //      not an issue in our system.\n    mapping(address => string) private implementationName;\n    mapping(address => Lib_AddressManager) private addressManager;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Lib_AddressManager.\n     * @param _implementationName implementationName of the contract to proxy to.\n     */\n    constructor(address _libAddressManager, string memory _implementationName) {\n        addressManager[address(this)] = Lib_AddressManager(_libAddressManager);\n        implementationName[address(this)] = _implementationName;\n    }\n\n    /*********************\n     * Fallback Function *\n     *********************/\n\n    fallback() external payable {\n        address target = addressManager[address(this)].getAddress(\n            (implementationName[address(this)])\n        );\n\n        require(target != address(0), \"Target address must be initialized.\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(msg.data);\n\n        if (success == true) {\n            assembly {\n                return(add(returndata, 0x20), mload(returndata))\n            }\n        } else {\n            assembly {\n                revert(add(returndata, 0x20), mload(returndata))\n            }\n        }\n    }\n}\n"
    },
    "contracts/L1/messaging/L1StandardBridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { IL1StandardBridge } from \"./IL1StandardBridge.sol\";\nimport { IL1ERC20Bridge } from \"./IL1ERC20Bridge.sol\";\nimport { IL2ERC20Bridge } from \"../../L2/messaging/IL2ERC20Bridge.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/* Library Imports */\nimport { CrossDomainEnabled } from \"../../libraries/bridge/CrossDomainEnabled.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { iMVM_DiscountOracle } from \"../../MVM/iMVM_DiscountOracle.sol\";\nimport { Lib_AddressManager } from \"../../libraries/resolver/Lib_AddressManager.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/**\n * @title L1StandardBridge\n * @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard\n * tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits\n * and listening to it for newly finalized withdrawals.\n *\n * Runtime target: EVM\n */\ncontract L1StandardBridge is IL1StandardBridge, CrossDomainEnabled {\n    using SafeERC20 for IERC20;\n\n    /********************************\n     * External Contract References *\n     ********************************/\n\n    address public l2TokenBridge;\n    address public metis;\n    address public addressmgr;\n\n    // Maps L1 token to chainid to L2 token to balance of the L1 token deposited\n    mapping(address => mapping(uint256 => mapping(address => uint256))) public deposits;\n\n    uint256 public constant DEFAULT_CHAINID = 1088;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    // This contract lives behind a proxy, so the constructor parameters will go unused.\n    constructor() CrossDomainEnabled(address(0)) {}\n\n    /******************\n     * Initialization *\n     ******************/\n\n    /**\n     * @param _l1messenger L1 Messenger address being used for cross-chain communications.\n     * @param _l2TokenBridge L2 standard bridge address.\n     */\n    function initialize(\n        address _l1messenger,\n        address _l2TokenBridge,\n        address _metis,\n        address _addressmgr\n    ) public {\n        require(messenger == address(0), \"Contract has already been initialized.\");\n        messenger = _l1messenger;\n        l2TokenBridge = _l2TokenBridge;\n        metis = _metis;\n        addressmgr = _addressmgr;\n    }\n\n    /**************\n     * Depositing *\n     **************/\n\n    /** @dev Modifier requiring sender to be EOA.  This check could be bypassed by a malicious\n     *  contract via initcode, but it takes care of the user error we want to avoid.\n     */\n    modifier onlyEOA() {\n        // Used to stop deposits from contracts (avoid accidentally lost tokens)\n        require(!Address.isContract(msg.sender), \"Account not EOA\");\n        _;\n    }\n\n    /**\n     * @dev do not accept no data call\n     */\n    //receive() external payable onlyEOA {\n    //    _initiateETHDeposit(msg.sender, msg.sender, 200_000, bytes(\"\"));\n    //}\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA {\n        _initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data);\n    }\n\n    function depositETHByChainId(\n        uint256 _chainId,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable override onlyEOA {\n        _initiateETHDepositByChainId(_chainId, msg.sender, msg.sender, _l2Gas, _data);\n    }\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function depositETHTo(\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable {\n        _initiateETHDeposit(msg.sender, _to, _l2Gas, _data);\n    }\n\n    function depositETHToByChainId(\n        uint256 _chainId,\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable override {\n        _initiateETHDepositByChainId(_chainId, msg.sender, _to, _l2Gas, _data);\n    }\n\n    /**\n     * @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of\n     * the deposit.\n     * @param _from Account to pull the deposit from on L1.\n     * @param _to Account to give the deposit to on L2.\n     * @param _l2Gas Gas limit required to complete the deposit on L2,\n     *        it should equal to or large than oracle.getMinL2Gas(),\n     *        user should send at least _l2Gas * oracle.getDiscount().\n     *        Bridging tokens and coins require paying fees, and there is the defined minimal L2 Gas limit,\n     *        which may make the defined by user Gas value increase.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateETHDeposit(\n        address _from,\n        address _to,\n        uint32 _l2Gas,\n        bytes memory _data\n    ) internal {\n        _initiateETHDepositByChainId(DEFAULT_CHAINID, _from, _to, _l2Gas, _data);\n    }\n\n    /**\n     * @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of\n     * the deposit.\n     * @param _chainId L2 chain id.\n     * @param _from Account to pull the deposit from on L1.\n     * @param _to Account to give the deposit to on L2.\n     * @param _l2Gas Gas limit required to complete the deposit on L2,\n     *        it should equal to or large than oracle.getMinL2Gas(),\n     *        user should send at least _l2Gas * oracle.getDiscount().\n     *        Bridging tokens and coins require paying fees, and there is the defined minimal L2 Gas limit,\n     *        which may make the defined by user Gas value increase.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateETHDepositByChainId(\n        uint256 _chainId,\n        address _from,\n        address _to,\n        uint32 _l2Gas,\n        bytes memory _data\n    ) internal {\n        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(\n            Lib_AddressManager(addressmgr).getAddress(\"MVM_DiscountOracle\")\n        );\n        uint32 mingas = uint32(oracle.getMinL2Gas());\n        if (_l2Gas < mingas) {\n            _l2Gas = mingas;\n        }\n        uint256 fee = _l2Gas * oracle.getDiscount();\n\n        require(\n            fee < msg.value,\n            string(\n                abi.encodePacked(\n                    \"insufficient fee supplied. send at least \",\n                    Lib_Uint.uint2str(fee)\n                )\n            )\n        );\n        // Construct calldata for finalizeDeposit call\n        bytes memory message = abi.encodeWithSelector(\n            IL2ERC20Bridge.finalizeDeposit.selector,\n            address(0),\n            Lib_PredeployAddresses.OVM_ETH,\n            _from,\n            _to,\n            msg.value - fee,\n            _data\n        );\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            l2TokenBridge,\n            _l2Gas,\n            message,\n            fee // only send the supplied fees over (obviously)\n        );\n\n        emit ETHDepositInitiated(_from, _to, msg.value - fee, _data, _chainId);\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function depositERC20(\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external virtual onlyEOA {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            msg.sender,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function depositERC20To(\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external virtual {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    function depositERC20ByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable virtual override onlyEOA {\n        _initiateERC20DepositByChainId(\n            _chainid,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            msg.sender,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    function depositERC20ToByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable virtual override {\n        _initiateERC20DepositByChainId(\n            _chainid,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @dev Performs the logic for deposits by informing the L2 Deposited Token\n     * contract of the deposit and calling a handler to lock the L1 funds. (e.g. transferFrom)\n     *\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _from Account to pull the deposit from on L1\n     * @param _to Account to give the deposit to on L2\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _l2Gas Gas limit required to complete the deposit on L2,\n     *        it should equal to or large than oracle.getMinL2Gas(),\n     *        user should send at least _l2Gas * oracle.getDiscount().\n     *        Bridging tokens and coins require paying fees, and there is the defined minimal L2 Gas limit,\n     *        which may make the defined by user Gas value increase.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateERC20Deposit(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) internal {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            _from,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @dev Performs the logic for deposits by informing the L2 Deposited Token\n     * contract of the deposit and calling a handler to lock the L1 funds. (e.g. transferFrom)\n     *\n     * @param _chainId L2 chain id\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _from Account to pull the deposit from on L1\n     * @param _to Account to give the deposit to on L2\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _l2Gas Gas limit required to complete the deposit on L2,\n     *        it should equal to or large than oracle.getMinL2Gas(),\n     *        user should send at least _l2Gas * oracle.getDiscount().\n     *        Bridging tokens and coins require paying fees, and there is the defined minimal L2 Gas limit,\n     *        which may make the defined by user Gas value increase.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateERC20DepositByChainId(\n        uint256 _chainId,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) internal {\n        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(\n            Lib_AddressManager(addressmgr).getAddress(\"MVM_DiscountOracle\")\n        );\n\n        // stack too deep. so no more local variables\n        if (_l2Gas < uint32(oracle.getMinL2Gas())) {\n            _l2Gas = uint32(oracle.getMinL2Gas());\n        }\n\n        require(\n            _l2Gas * oracle.getDiscount() <= msg.value,\n            string(\n                abi.encodePacked(\n                    \"insufficient fee supplied. send at least \",\n                    Lib_Uint.uint2str(_l2Gas * oracle.getDiscount())\n                )\n            )\n        );\n\n        // When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future\n        // withdrawals. safeTransferFrom also checks if the contract has code, so this will fail if\n        // _from is an EOA or address(0).\n        IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);\n\n        bytes memory message;\n        if (_l1Token == metis) {\n            // Construct calldata for finalizeDeposit call\n            _l2Token = Lib_PredeployAddresses.MVM_COINBASE;\n            message = abi.encodeWithSelector(\n                IL2ERC20Bridge.finalizeDeposit.selector,\n                address(0),\n                Lib_PredeployAddresses.MVM_COINBASE,\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        } else {\n            // Construct calldata for finalizeDeposit call\n            message = abi.encodeWithSelector(\n                IL2ERC20Bridge.finalizeDeposit.selector,\n                _l1Token,\n                _l2Token,\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        }\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            l2TokenBridge,\n            _l2Gas,\n            message,\n            msg.value //send all values as fees to cover l2 tx cost\n        );\n\n        deposits[_l1Token][_chainId][_l2Token] = deposits[_l1Token][_chainId][_l2Token] + (_amount);\n\n        emit ERC20ChainID(_chainId);\n        emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function finalizeETHWithdrawal(\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external onlyFromCrossDomainAccount(l2TokenBridge) {\n        (bool success, ) = _to.call{ value: _amount }(new bytes(0));\n        require(success, \"TransferHelper::safeTransferETH: ETH transfer failed\");\n\n        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, DEFAULT_CHAINID);\n    }\n\n    function finalizeETHWithdrawalByChainId(\n        uint256 _chainid,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        (bool success, ) = _to.call{ value: _amount }(new bytes(0));\n        require(success, \"TransferHelper::safeTransferETH: ETH transfer failed\");\n\n        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, _chainid);\n    }\n\n    function finalizeMetisWithdrawalByChainId(\n        uint256 _chainid,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        _finalizeERC20WithdrawalByChainId(\n            _chainid,\n            metis,\n            Lib_PredeployAddresses.MVM_COINBASE,\n            _from,\n            _to,\n            _amount,\n            _data\n        );\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function finalizeERC20Withdrawal(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external onlyFromCrossDomainAccount(l2TokenBridge) {\n        _finalizeERC20WithdrawalByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            _from,\n            _to,\n            _amount,\n            _data\n        );\n    }\n\n    function finalizeERC20WithdrawalByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        _finalizeERC20WithdrawalByChainId(_chainid, _l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    function _finalizeERC20WithdrawalByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) internal {\n        deposits[_l1Token][_chainid][_l2Token] = deposits[_l1Token][_chainid][_l2Token] - _amount;\n\n        // When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer\n        IERC20(_l1Token).safeTransfer(_to, _amount);\n\n        emit ERC20ChainID(_chainid);\n        emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    /*****************************\n     * Temporary - Migrating ETH *\n     *****************************/\n\n    /**\n     * @dev Adds ETH balance to the account. This is meant to allow for ETH\n     * to be migrated from an old gateway to a new gateway.\n     * NOTE: This is left for one upgrade only so we are able to receive the migrated ETH from the\n     * old contract\n     */\n    function donateETH() external payable {}\n}\n"
    },
    "contracts/L2/predeploys/OVM_ETH.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/* Contract Imports */\nimport { L2StandardERC20 } from \"../../standards/L2StandardERC20.sol\";\n\n/**\n * @title OVM_ETH\n * @dev The ETH predeploy provides an ERC20 interface for ETH deposited to Layer 2. Note that\n * unlike on Layer 1, Layer 2 accounts do not have a balance field.\n */\ncontract OVM_ETH is L2StandardERC20 {\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor()\n        L2StandardERC20(Lib_PredeployAddresses.L2_STANDARD_BRIDGE, address(0), \"Ether\", \"WETH\")\n    {}\n}\n"
    },
    "contracts/L2/messaging/L2StandardTokenFactory.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Contract Imports */\nimport { L2StandardERC20 } from \"../../standards/L2StandardERC20.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/**\n * @title L2StandardTokenFactory\n * @dev Factory contract for creating standard L2 token representations of L1 ERC20s\n * compatible with and working on the standard bridge.\n */\ncontract L2StandardTokenFactory {\n    event StandardL2TokenCreated(address indexed _l1Token, address indexed _l2Token);\n\n    /**\n     * @dev Creates an instance of the standard ERC20 token on L2.\n     * @param _l1Token Address of the corresponding L1 token.\n     * @param _name ERC20 name.\n     * @param _symbol ERC20 symbol.\n     */\n    function createStandardL2Token(\n        address _l1Token,\n        string memory _name,\n        string memory _symbol\n    ) external {\n        require(_l1Token != address(0), \"Must provide L1 token address\");\n\n        L2StandardERC20 l2Token = new L2StandardERC20(\n            Lib_PredeployAddresses.L2_STANDARD_BRIDGE,\n            _l1Token,\n            _name,\n            _symbol\n        );\n\n        emit StandardL2TokenCreated(_l1Token, address(l2Token));\n    }\n}\n"
    },
    "contracts/L2/predeploys/OVM_L2ToL1MessagePasser.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { iOVM_L2ToL1MessagePasser } from \"./iOVM_L2ToL1MessagePasser.sol\";\n\n/**\n * @title OVM_L2ToL1MessagePasser\n * @dev The L2 to L1 Message Passer is a utility contract which facilitate an L1 proof of the\n * of a message on L2. The L1 Cross Domain Messenger performs this proof in its\n * _verifyStorageProof function, which verifies the existence of the transaction hash in this\n * contract's `sentMessages` mapping.\n\n */\ncontract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {\n    /**********************\n     * Contract Variables *\n     **********************/\n\n    mapping(bytes32 => bool) public sentMessages;\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Passes a message to L1.\n     * @param _message Message to pass to L1.\n     */\n    function passMessageToL1(bytes memory _message) public {\n        // Note: although this function is public, only messages sent from the\n        // L2CrossDomainMessenger will be relayed by the L1CrossDomainMessenger.\n        // This is enforced by a check in L1CrossDomainMessenger._verifyStorageProof().\n        sentMessages[keccak256(abi.encodePacked(_message, msg.sender))] = true;\n    }\n}\n"
    },
    "contracts/test-libraries/standards/TestLib_AddressAliasHelper.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/* Library Imports */\nimport { AddressAliasHelper } from \"../../standards/AddressAliasHelper.sol\";\n\n/**\n * @title TestLib_AddressAliasHelper\n */\ncontract TestLib_AddressAliasHelper {\n    function applyL1ToL2Alias(address _address) public pure returns (address) {\n        return AddressAliasHelper.applyL1ToL2Alias(_address);\n    }\n\n    function undoL1ToL2Alias(address _address) public pure returns (address) {\n        return AddressAliasHelper.undoL1ToL2Alias(_address);\n    }\n}\n"
    },
    "contracts/test-libraries/trie/TestLib_MerkleTrie.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_MerkleTrie } from \"../../libraries/trie/Lib_MerkleTrie.sol\";\n\n/**\n * @title TestLib_MerkleTrie\n */\ncontract TestLib_MerkleTrie {\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bool) {\n        return Lib_MerkleTrie.verifyInclusionProof(_key, _value, _proof, _root);\n    }\n\n    function update(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bytes32) {\n        return Lib_MerkleTrie.update(_key, _value, _proof, _root);\n    }\n\n    function get(\n        bytes memory _key,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bool, bytes memory) {\n        return Lib_MerkleTrie.get(_key, _proof, _root);\n    }\n\n    function getSingleNodeRootHash(bytes memory _key, bytes memory _value)\n        public\n        pure\n        returns (bytes32)\n    {\n        return Lib_MerkleTrie.getSingleNodeRootHash(_key, _value);\n    }\n}\n"
    },
    "contracts/test-libraries/rlp/TestLib_RLPWriter.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_RLPWriter } from \"../../libraries/rlp/Lib_RLPWriter.sol\";\nimport { TestERC20 } from \"../../test-helpers/TestERC20.sol\";\n\n/**\n * @title TestLib_RLPWriter\n */\ncontract TestLib_RLPWriter {\n    function writeBytes(bytes memory _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeBytes(_in);\n    }\n\n    function writeList(bytes[] memory _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeList(_in);\n    }\n\n    function writeString(string memory _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeString(_in);\n    }\n\n    function writeAddress(address _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeAddress(_in);\n    }\n\n    function writeUint(uint256 _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeUint(_in);\n    }\n\n    function writeBool(bool _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeBool(_in);\n    }\n\n    function writeAddressWithTaintedMemory(address _in) public returns (bytes memory _out) {\n        new TestERC20();\n        return Lib_RLPWriter.writeAddress(_in);\n    }\n}\n"
    },
    "contracts/test-helpers/TestERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n// a test ERC20 token with an open mint function\ncontract TestERC20 {\n    string public constant name = \"Test\";\n    string public constant symbol = \"TST\";\n    uint8 public constant decimals = 18;\n    uint256 public totalSupply;\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    constructor() {}\n\n    function mint(address to, uint256 value) public {\n        totalSupply = totalSupply + value;\n        balanceOf[to] = balanceOf[to] + value;\n        emit Transfer(address(0), to, value);\n    }\n\n    function _approve(\n        address owner,\n        address spender,\n        uint256 value\n    ) private {\n        allowance[owner][spender] = value;\n        emit Approval(owner, spender, value);\n    }\n\n    function _transfer(\n        address from,\n        address to,\n        uint256 value\n    ) private {\n        balanceOf[from] = balanceOf[from] - value;\n        balanceOf[to] = balanceOf[to] + value;\n        emit Transfer(from, to, value);\n    }\n\n    function approve(address spender, uint256 value) external returns (bool) {\n        _approve(msg.sender, spender, value);\n        return true;\n    }\n\n    function transfer(address to, uint256 value) external returns (bool) {\n        _transfer(msg.sender, to, value);\n        return true;\n    }\n\n    function transferFrom(\n        address from,\n        address to,\n        uint256 value\n    ) external returns (bool) {\n        if (allowance[from][msg.sender] != type(uint256).max) {\n            allowance[from][msg.sender] = allowance[from][msg.sender] - value;\n        }\n        _transfer(from, to, value);\n        return true;\n    }\n}\n"
    },
    "contracts/test-libraries/utils/TestLib_BytesUtils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_BytesUtils } from \"../../libraries/utils/Lib_BytesUtils.sol\";\nimport { TestERC20 } from \"../../test-helpers/TestERC20.sol\";\n\n/**\n * @title TestLib_BytesUtils\n */\ncontract TestLib_BytesUtils {\n    function concat(bytes memory _preBytes, bytes memory _postBytes)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(_preBytes, _postBytes);\n    }\n\n    function slice(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    ) public pure returns (bytes memory) {\n        return Lib_BytesUtils.slice(_bytes, _start, _length);\n    }\n\n    function toBytes32(bytes memory _bytes) public pure returns (bytes32) {\n        return Lib_BytesUtils.toBytes32(_bytes);\n    }\n\n    function toUint256(bytes memory _bytes) public pure returns (uint256) {\n        return Lib_BytesUtils.toUint256(_bytes);\n    }\n\n    function toNibbles(bytes memory _bytes) public pure returns (bytes memory) {\n        return Lib_BytesUtils.toNibbles(_bytes);\n    }\n\n    function fromNibbles(bytes memory _bytes) public pure returns (bytes memory) {\n        return Lib_BytesUtils.fromNibbles(_bytes);\n    }\n\n    function equal(bytes memory _bytes, bytes memory _other) public pure returns (bool) {\n        return Lib_BytesUtils.equal(_bytes, _other);\n    }\n\n    function sliceWithTaintedMemory(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    ) public returns (bytes memory) {\n        new TestERC20();\n        return Lib_BytesUtils.slice(_bytes, _start, _length);\n    }\n}\n"
    },
    "contracts/test-libraries/trie/TestLib_SecureMerkleTrie.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_SecureMerkleTrie } from \"../../libraries/trie/Lib_SecureMerkleTrie.sol\";\n\n/**\n * @title TestLib_SecureMerkleTrie\n */\ncontract TestLib_SecureMerkleTrie {\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bool) {\n        return Lib_SecureMerkleTrie.verifyInclusionProof(_key, _value, _proof, _root);\n    }\n\n    function update(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bytes32) {\n        return Lib_SecureMerkleTrie.update(_key, _value, _proof, _root);\n    }\n\n    function get(\n        bytes memory _key,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bool, bytes memory) {\n        return Lib_SecureMerkleTrie.get(_key, _proof, _root);\n    }\n\n    function getSingleNodeRootHash(bytes memory _key, bytes memory _value)\n        public\n        pure\n        returns (bytes32)\n    {\n        return Lib_SecureMerkleTrie.getSingleNodeRootHash(_key, _value);\n    }\n}\n"
    },
    "contracts/test-libraries/utils/TestLib_MerkleTree.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_MerkleTree } from \"../../libraries/utils/Lib_MerkleTree.sol\";\n\n/**\n * @title TestLib_MerkleTree\n */\ncontract TestLib_MerkleTree {\n    function getMerkleRoot(bytes32[] memory _elements) public pure returns (bytes32) {\n        return Lib_MerkleTree.getMerkleRoot(_elements);\n    }\n\n    function verify(\n        bytes32 _root,\n        bytes32 _leaf,\n        uint256 _index,\n        bytes32[] memory _siblings,\n        uint256 _totalLeaves\n    ) public pure returns (bool) {\n        return Lib_MerkleTree.verify(_root, _leaf, _index, _siblings, _totalLeaves);\n    }\n}\n"
    },
    "contracts/L1/rollup/ChainStorageContainer.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_Buffer } from \"../../libraries/utils/Lib_Buffer.sol\";\nimport { Lib_AddressResolver } from \"../../libraries/resolver/Lib_AddressResolver.sol\";\n\n/* Interface Imports */\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title ChainStorageContainer\n * @dev The Chain Storage Container provides its owner contract with read, write and delete\n * functionality. This provides gas efficiency gains by enabling it to overwrite storage slots which\n * can no longer be used in a fraud proof due to the fraud window having passed, and the associated\n * chain state or transactions being finalized.\n * Two distinct Chain Storage Containers will be deployed on Layer 1:\n * 1. Stores transaction batches for the Canonical Transaction Chain\n * 2. Stores chain state batches for the State Commitment Chain\n *\n * Runtime target: EVM\n */\ncontract ChainStorageContainer is IChainStorageContainer, Lib_AddressResolver {\n    /*************\n     * Libraries *\n     *************/\n\n    using Lib_Buffer for Lib_Buffer.Buffer;\n\n    /**************\n     *  constant  *\n     **************/\n    uint256 public constant DEFAULT_CHAINID = 1088;\n\n    /*************\n     * Variables *\n     *************/\n\n    string public owner;\n    mapping(uint256 => Lib_Buffer.Buffer) internal buffers;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     * @param _owner Name of the contract that owns this container (will be resolved later).\n     */\n    constructor(address _libAddressManager, string memory _owner)\n        Lib_AddressResolver(_libAddressManager)\n    {\n        owner = _owner;\n    }\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    modifier onlyOwner() {\n        require(\n            msg.sender == resolve(owner),\n            \"ChainStorageContainer: Function can only be called by the owner.\"\n        );\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function setGlobalMetadata(bytes27 _globalMetadata) public onlyOwner {\n        return setGlobalMetadataByChainId(DEFAULT_CHAINID, _globalMetadata);\n    }\n\n    function setByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes32 _object\n    ) public override onlyOwner {\n        buffers[_chainId].set(_index, _object);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function setGlobalMetadataByChainId(uint256 _chainId, bytes27 _globalMetadata)\n        public\n        override\n        onlyOwner\n    {\n        return buffers[_chainId].setExtraData(_globalMetadata);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function getGlobalMetadata() public view returns (bytes27) {\n        return getGlobalMetadataByChainId(DEFAULT_CHAINID);\n    }\n\n    function getGlobalMetadataByChainId(uint256 _chainId) public view override returns (bytes27) {\n        return buffers[_chainId].getExtraData();\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function length() public view returns (uint256) {\n        return lengthByChainId(DEFAULT_CHAINID);\n    }\n\n    function lengthByChainId(uint256 _chainId) public view override returns (uint256) {\n        return uint256(buffers[_chainId].getLength());\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function push(bytes32 _object) public onlyOwner {\n        pushByChainId(DEFAULT_CHAINID, _object);\n    }\n\n    function pushByChainId(uint256 _chainId, bytes32 _object) public override onlyOwner {\n        buffers[_chainId].push(_object);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function push(bytes32 _object, bytes27 _globalMetadata) public onlyOwner {\n        pushByChainId(DEFAULT_CHAINID, _object, _globalMetadata);\n    }\n\n    function pushByChainId(\n        uint256 _chainId,\n        bytes32 _object,\n        bytes27 _globalMetadata\n    ) public override onlyOwner {\n        buffers[_chainId].push(_object, _globalMetadata);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function get(uint256 _index) public view returns (bytes32) {\n        return getByChainId(DEFAULT_CHAINID, _index);\n    }\n\n    function getByChainId(uint256 _chainId, uint256 _index) public view override returns (bytes32) {\n        return buffers[_chainId].get(uint40(_index));\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function deleteElementsAfterInclusive(uint256 _index) public onlyOwner {\n        deleteElementsAfterInclusiveByChainId(DEFAULT_CHAINID, _index);\n    }\n\n    function deleteElementsAfterInclusiveByChainId(uint256 _chainId, uint256 _index)\n        public\n        override\n        onlyOwner\n    {\n        buffers[_chainId].deleteElementsAfterInclusive(uint40(_index));\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function deleteElementsAfterInclusive(uint256 _index, bytes27 _globalMetadata)\n        public\n        onlyOwner\n    {\n        deleteElementsAfterInclusiveByChainId(DEFAULT_CHAINID, _index, _globalMetadata);\n    }\n\n    function deleteElementsAfterInclusiveByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    ) public override onlyOwner {\n        buffers[_chainId].deleteElementsAfterInclusive(uint40(_index), _globalMetadata);\n    }\n}\n"
    },
    "contracts/libraries/utils/Lib_Buffer.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_Buffer\n * @dev This library implements a bytes32 storage array with some additional gas-optimized\n * functionality. In particular, it encodes its length as a uint40, and tightly packs this with an\n * overwritable \"extra data\" field so we can store more information with a single SSTORE.\n */\nlibrary Lib_Buffer {\n    /*************\n     * Libraries *\n     *************/\n\n    using Lib_Buffer for Buffer;\n\n    /***********\n     * Structs *\n     ***********/\n\n    struct Buffer {\n        bytes32 context;\n        mapping(uint256 => bytes32) buf;\n    }\n\n    struct BufferContext {\n        // Stores the length of the array. Uint40 is way more elements than we'll ever reasonably\n        // need in an array and we get an extra 27 bytes of extra data to play with.\n        uint40 length;\n        // Arbitrary extra data that can be modified whenever the length is updated. Useful for\n        // squeezing out some gas optimizations.\n        bytes27 extraData;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Pushes a single element to the buffer.\n     * @param _self Buffer to access.\n     * @param _value Value to push to the buffer.\n     * @param _extraData Global extra data.\n     */\n    function push(\n        Buffer storage _self,\n        bytes32 _value,\n        bytes27 _extraData\n    ) internal {\n        BufferContext memory ctx = _self.getContext();\n\n        _self.buf[ctx.length] = _value;\n\n        // Bump the global index and insert our extra data, then save the context.\n        ctx.length++;\n        ctx.extraData = _extraData;\n        _self.setContext(ctx);\n    }\n\n    /**\n     * Pushes a single element to the buffer.\n     * @param _self Buffer to access.\n     * @param _value Value to push to the buffer.\n     */\n    function push(Buffer storage _self, bytes32 _value) internal {\n        BufferContext memory ctx = _self.getContext();\n\n        _self.push(_value, ctx.extraData);\n    }\n\n    /**\n     * Retrieves an element from the buffer.\n     * @param _self Buffer to access.\n     * @param _index Element index to retrieve.\n     * @return Value of the element at the given index.\n     */\n    function get(Buffer storage _self, uint256 _index) internal view returns (bytes32) {\n        BufferContext memory ctx = _self.getContext();\n\n        require(_index < ctx.length, \"Index out of bounds.\");\n\n        return _self.buf[_index];\n    }\n\n    /**\n     * Deletes all elements after (and including) a given index.\n     * @param _self Buffer to access.\n     * @param _index Index of the element to delete from (inclusive).\n     * @param _extraData Optional global extra data.\n     */\n    function deleteElementsAfterInclusive(\n        Buffer storage _self,\n        uint40 _index,\n        bytes27 _extraData\n    ) internal {\n        BufferContext memory ctx = _self.getContext();\n\n        require(_index < ctx.length, \"Index out of bounds.\");\n\n        // Set our length and extra data, save the context.\n        ctx.length = _index;\n        ctx.extraData = _extraData;\n        _self.setContext(ctx);\n    }\n\n    /**\n     * Deletes all elements after (and including) a given index.\n     * @param _self Buffer to access.\n     * @param _index Index of the element to delete from (inclusive).\n     */\n    function deleteElementsAfterInclusive(Buffer storage _self, uint40 _index) internal {\n        BufferContext memory ctx = _self.getContext();\n        _self.deleteElementsAfterInclusive(_index, ctx.extraData);\n    }\n\n    /**\n     * Retrieves the current global index.\n     * @param _self Buffer to access.\n     * @return Current global index.\n     */\n    function getLength(Buffer storage _self) internal view returns (uint40) {\n        BufferContext memory ctx = _self.getContext();\n        return ctx.length;\n    }\n\n    /**\n     * Changes current global extra data.\n     * @param _self Buffer to access.\n     * @param _extraData New global extra data.\n     */\n    function setExtraData(Buffer storage _self, bytes27 _extraData) internal {\n        BufferContext memory ctx = _self.getContext();\n        ctx.extraData = _extraData;\n        _self.setContext(ctx);\n    }\n\n    /**\n     * Retrieves the current global extra data.\n     * @param _self Buffer to access.\n     * @return Current global extra data.\n     */\n    function getExtraData(Buffer storage _self) internal view returns (bytes27) {\n        BufferContext memory ctx = _self.getContext();\n        return ctx.extraData;\n    }\n\n    /**\n     * Sets the current buffer context.\n     * @param _self Buffer to access.\n     * @param _ctx Current buffer context.\n     */\n    function setContext(Buffer storage _self, BufferContext memory _ctx) internal {\n        bytes32 context;\n        uint40 length = _ctx.length;\n        bytes27 extraData = _ctx.extraData;\n        assembly {\n            context := length\n            context := or(context, extraData)\n        }\n\n        if (_self.context != context) {\n            _self.context = context;\n        }\n    }\n\n    /**\n     * Retrieves the current buffer context.\n     * @param _self Buffer to access.\n     * @return Current buffer context.\n     */\n    function getContext(Buffer storage _self) internal view returns (BufferContext memory) {\n        bytes32 context = _self.context;\n        uint40 length;\n        bytes27 extraData;\n        assembly {\n            length := and(\n                context,\n                0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n            )\n            extraData := and(\n                context,\n                0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000\n            )\n        }\n\n        return BufferContext({ length: length, extraData: extraData });\n    }\n\n    /**\n     * set elements for a given index.\n     * @param _self Buffer to access.\n     * @param _index Index of the element to set.\n     * @param _value value to set\n     */\n    function set(\n        Buffer storage _self,\n        uint256 _index,\n        bytes32 _value\n    ) internal {\n        BufferContext memory ctx = _self.getContext();\n        require(_index < ctx.length, \"Index out of bounds.\");\n        _self.buf[_index] = _value;\n    }\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 10000
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}