{
  "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    /*******************\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    /********************\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 _gasLimit Gas limit for the provided message.\n     */\n    function replayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _queueIndex,\n        uint32 _gasLimit\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\";\nimport { Lib_RLPWriter } from \"../rlp/Lib_RLPWriter.sol\";\nimport { Lib_BytesUtils } from \"../utils/Lib_BytesUtils.sol\";\nimport { Lib_Bytes32Utils } from \"../utils/Lib_Bytes32Utils.sol\";\n\n/**\n * @title Lib_OVMCodec\n */\nlibrary Lib_OVMCodec {\n\n    /*********\n     * Enums *\n     *********/\n\n    enum QueueOrigin {\n        SEQUENCER_QUEUE,\n        L1TOL2_QUEUE\n    }\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    /**********************\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(\n        Transaction memory _transaction\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\n        return 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(\n        Transaction memory _transaction\n    )\n        internal\n        pure\n        returns (\n            bytes32\n        )\n    {\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(\n        bytes memory _encoded\n    )\n        internal\n        pure\n        returns (\n            EVMAccount memory\n        )\n    {\n        Lib_RLPReader.RLPItem[] memory accountState = Lib_RLPReader.readList(_encoded);\n\n        return 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(\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    )\n        internal\n        pure\n        returns (\n            bytes32\n        )\n    {\n        return 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    /**********\n     * Events *\n     **********/\n\n    event SentMessage(\n        address indexed target,\n        address sender,\n        bytes message,\n        uint256 messageNonce,\n        uint256 gasLimit);\n    event RelayedMessage(bytes32 indexed msgHash);\n    event FailedRelayedMessage(bytes32 indexed msgHash);\n\n\n    /*************\n     * Variables *\n     *************/\n\n    function xDomainMessageSender() external view returns (address);\n\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;\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    /*************\n     * Constants *\n     *************/\n\n    uint256 constant internal MAX_LIST_LENGTH = 32;\n\n\n    /*********\n     * Enums *\n     *********/\n\n    enum RLPItemType {\n        DATA_ITEM,\n        LIST_ITEM\n    }\n\n\n    /***********\n     * Structs *\n     ***********/\n\n    struct RLPItem {\n        uint256 length;\n        uint256 ptr;\n    }\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(\n        bytes memory _in\n    )\n        internal\n        pure\n        returns (\n            RLPItem memory\n        )\n    {\n        uint256 ptr;\n        assembly {\n            ptr := add(_in, 32)\n        }\n\n        return RLPItem({\n            length: _in.length,\n            ptr: ptr\n        });\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(\n        RLPItem memory _in\n    )\n        internal\n        pure\n        returns (\n            RLPItem[] memory\n        )\n    {\n        (\n            uint256 listOffset,\n            ,\n            RLPItemType itemType\n        ) = _decodeLength(_in);\n\n        require(\n            itemType == RLPItemType.LIST_ITEM,\n            \"Invalid RLP list value.\"\n        );\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(\n                itemCount < MAX_LIST_LENGTH,\n                \"Provided RLP list exceeds max list length.\"\n            );\n\n            (\n                uint256 itemOffset,\n                uint256 itemLength,\n            ) = _decodeLength(RLPItem({\n                length: _in.length - offset,\n                ptr: _in.ptr + offset\n            }));\n\n            out[itemCount] = RLPItem({\n                length: itemLength + itemOffset,\n                ptr: _in.ptr + offset\n            });\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(\n        bytes memory _in\n    )\n        internal\n        pure\n        returns (\n            RLPItem[] memory\n        )\n    {\n        return readList(\n            toRLPItem(_in)\n        );\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(\n        RLPItem memory _in\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\n        (\n            uint256 itemOffset,\n            uint256 itemLength,\n            RLPItemType itemType\n        ) = _decodeLength(_in);\n\n        require(\n            itemType == RLPItemType.DATA_ITEM,\n            \"Invalid RLP bytes value.\"\n        );\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(\n        bytes memory _in\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\n        return readBytes(\n            toRLPItem(_in)\n        );\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(\n        RLPItem memory _in\n    )\n        internal\n        pure\n        returns (\n            string memory\n        )\n    {\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(\n        bytes memory _in\n    )\n        internal\n        pure\n        returns (\n            string memory\n        )\n    {\n        return readString(\n            toRLPItem(_in)\n        );\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(\n        RLPItem memory _in\n    )\n        internal\n        pure\n        returns (\n            bytes32\n        )\n    {\n        require(\n            _in.length <= 33,\n            \"Invalid RLP bytes32 value.\"\n        );\n\n        (\n            uint256 itemOffset,\n            uint256 itemLength,\n            RLPItemType itemType\n        ) = _decodeLength(_in);\n\n        require(\n            itemType == RLPItemType.DATA_ITEM,\n            \"Invalid RLP bytes32 value.\"\n        );\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(\n        bytes memory _in\n    )\n        internal\n        pure\n        returns (\n            bytes32\n        )\n    {\n        return readBytes32(\n            toRLPItem(_in)\n        );\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(\n        RLPItem memory _in\n    )\n        internal\n        pure\n        returns (\n            uint256\n        )\n    {\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(\n        bytes memory _in\n    )\n        internal\n        pure\n        returns (\n            uint256\n        )\n    {\n        return readUint256(\n            toRLPItem(_in)\n        );\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(\n        RLPItem memory _in\n    )\n        internal\n        pure\n        returns (\n            bool\n        )\n    {\n        require(\n            _in.length == 1,\n            \"Invalid RLP boolean value.\"\n        );\n\n        uint256 ptr = _in.ptr;\n        uint256 out;\n        assembly {\n            out := byte(0, mload(ptr))\n        }\n\n        require(\n            out == 0 || out == 1,\n            \"Lib_RLPReader: Invalid RLP boolean value, must be 0 or 1\"\n        );\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(\n        bytes memory _in\n    )\n        internal\n        pure\n        returns (\n            bool\n        )\n    {\n        return readBool(\n            toRLPItem(_in)\n        );\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(\n        RLPItem memory _in\n    )\n        internal\n        pure\n        returns (\n            address\n        )\n    {\n        if (_in.length == 1) {\n            return address(0);\n        }\n\n        require(\n            _in.length == 21,\n            \"Invalid RLP address value.\"\n        );\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(\n        bytes memory _in\n    )\n        internal\n        pure\n        returns (\n            address\n        )\n    {\n        return readAddress(\n            toRLPItem(_in)\n        );\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(\n        RLPItem memory _in\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\n        return _copy(_in);\n    }\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(\n        RLPItem memory _in\n    )\n        private\n        pure\n        returns (\n            uint256,\n            uint256,\n            RLPItemType\n        )\n    {\n        require(\n            _in.length > 0,\n            \"RLP item cannot be null.\"\n        );\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(\n                _in.length > strLen,\n                \"Invalid RLP short string.\"\n            );\n\n            return (1, strLen, RLPItemType.DATA_ITEM);\n        } else if (prefix <= 0xbf) {\n            // Long string.\n            uint256 lenOfStrLen = prefix - 0xb7;\n\n            require(\n                _in.length > lenOfStrLen,\n                \"Invalid RLP long string length.\"\n            );\n\n            uint256 strLen;\n            assembly {\n                // Pick out the string length.\n                strLen := div(\n                    mload(add(ptr, 1)),\n                    exp(256, sub(32, lenOfStrLen))\n                )\n            }\n\n            require(\n                _in.length > lenOfStrLen + strLen,\n                \"Invalid RLP long string.\"\n            );\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(\n                _in.length > listLen,\n                \"Invalid RLP short list.\"\n            );\n\n            return (1, listLen, RLPItemType.LIST_ITEM);\n        } else {\n            // Long list.\n            uint256 lenOfListLen = prefix - 0xf7;\n\n            require(\n                _in.length > lenOfListLen,\n                \"Invalid RLP long list length.\"\n            );\n\n            uint256 listLen;\n            assembly {\n                // Pick out the list length.\n                listLen := div(\n                    mload(add(ptr, 1)),\n                    exp(256, sub(32, lenOfListLen))\n                )\n            }\n\n            require(\n                _in.length > lenOfListLen + listLen,\n                \"Invalid RLP long list.\"\n            );\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    )\n        private\n        pure\n        returns (\n            bytes memory\n        )\n    {\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(\n                dest,\n                or(\n                    and(mload(src), not(mask)),\n                    and(mload(dest), mask)\n                )\n            )\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(\n        RLPItem memory _in\n    )\n        private\n        pure\n        returns (\n            bytes memory\n        )\n    {\n        return _copy(_in.ptr, 0, _in.length);\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    /**********************\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(\n        bytes memory _in\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\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(\n        bytes[] memory _in\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\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(\n        string memory _in\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\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(\n        address _in\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\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(\n        uint256 _in\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\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(\n        bool _in\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\n        bytes memory encoded = new bytes(1);\n        encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\n        return encoded;\n    }\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(\n        uint256 _len,\n        uint256 _offset\n    )\n        private\n        pure\n        returns (\n            bytes memory\n        )\n    {\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(\n        uint256 _x\n    )\n        private\n        pure\n        returns (\n            bytes memory\n        )\n    {\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    )\n        private\n        pure\n    {\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(\n        bytes[] memory _list\n    )\n        private\n        pure\n        returns (\n            bytes memory\n        )\n    {\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 { flattenedPtr := add(flattened, 0x20) }\n\n        for(i = 0; i < _list.length; i++) {\n            bytes memory item = _list[i];\n\n            uint256 listPtr;\n            assembly { listPtr := add(item, 0x20)}\n\n            _memcpy(flattenedPtr, listPtr, item.length);\n            flattenedPtr += _list[i].length;\n        }\n\n        return flattened;\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    /**********************\n     * Internal Functions *\n     **********************/\n\n    function slice(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\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(\n        bytes memory _bytes,\n        uint256 _start\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\n        if (_start >= _bytes.length) {\n            return bytes(\"\");\n        }\n\n        return slice(_bytes, _start, _bytes.length - _start);\n    }\n\n    function toBytes32(\n        bytes memory _bytes\n    )\n        internal\n        pure\n        returns (\n            bytes32\n        )\n    {\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(\n        bytes memory _bytes\n    )\n        internal\n        pure\n        returns (\n            uint256\n        )\n    {\n        return uint256(toBytes32(_bytes));\n    }\n\n    function toNibbles(\n        bytes memory _bytes\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\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(\n        bytes memory _bytes\n    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\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(\n        bytes memory _bytes,\n        bytes memory _other\n    )\n        internal\n        pure\n        returns (\n            bool\n        )\n    {\n        return keccak256(_bytes) == keccak256(_other);\n    }\n}\n"
    },
    "contracts/libraries/utils/Lib_Bytes32Utils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_Byte32Utils\n */\nlibrary Lib_Bytes32Utils {\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Converts a bytes32 value to a boolean. Anything non-zero will be converted to \"true.\"\n     * @param _in Input bytes32 value.\n     * @return Bytes32 as a boolean.\n     */\n    function toBool(\n        bytes32 _in\n    )\n        internal\n        pure\n        returns (\n            bool\n        )\n    {\n        return _in != 0;\n    }\n\n    /**\n     * Converts a boolean to a bytes32 value.\n     * @param _in Input boolean value.\n     * @return Boolean as a bytes32.\n     */\n    function fromBool(\n        bool _in\n    )\n        internal\n        pure\n        returns (\n            bytes32\n        )\n    {\n        return bytes32(uint256(_in ? 1 : 0));\n    }\n\n    /**\n     * Converts a bytes32 value to an address. Takes the *last* 20 bytes.\n     * @param _in Input bytes32 value.\n     * @return Bytes32 as an address.\n     */\n    function toAddress(\n        bytes32 _in\n    )\n        internal\n        pure\n        returns (\n            address\n        )\n    {\n        return address(uint160(uint256(_in)));\n    }\n\n    /**\n     * Converts an address to a bytes32.\n     * @param _in Input address value.\n     * @return Address as a bytes32.\n     */\n    function fromAddress(\n        address _in\n    )\n        internal\n        pure\n        returns (\n            bytes32\n        )\n    {\n        return bytes32(uint256(uint160(_in)));\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\";\n\n/* External Imports */\nimport { OwnableUpgradeable } from\n    \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { PausableUpgradeable } from\n    \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from\n    \"@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    /**********\n     * Events *\n     **********/\n\n    event MessageBlocked(\n        bytes32 indexed _xDomainCalldataHash\n    );\n\n    event MessageAllowed(\n        bytes32 indexed _xDomainCalldataHash\n    );\n\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\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()\n        Lib_AddressResolver(address(0))\n    {}\n\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     */\n    function initialize(\n        address _libAddressManager\n    )\n        public\n        initializer\n    {\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()\n        external\n        onlyOwner\n    {\n        _pause();\n    }\n\n    /**\n     * Block a message.\n     * @param _xDomainCalldataHash Hash of the message to block.\n     */\n    function blockMessage(\n        bytes32 _xDomainCalldataHash\n    )\n        external\n        onlyOwner\n    {\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(\n        bytes32 _xDomainCalldataHash\n    )\n        external\n        onlyOwner\n    {\n        blockedMessages[_xDomainCalldataHash] = false;\n        emit MessageAllowed(_xDomainCalldataHash);\n    }\n\n    function xDomainMessageSender()\n        public\n        view\n        returns (\n            address\n        )\n    {\n        require(xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER, \"xDomainMessageSender is not set\");\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    )\n        public\n    {\n        address ovmCanonicalTransactionChain = resolve(\"CanonicalTransactionChain\");\n        // Use the CTC queue length as nonce\n        uint40 nonce =\n            ICanonicalTransactionChain(ovmCanonicalTransactionChain).getQueueLength();\n\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            msg.sender,\n            _message,\n            nonce\n        );\n\n        _sendXDomainMessage(\n            ovmCanonicalTransactionChain,\n            xDomainCalldata,\n            _gasLimit\n        );\n\n        emit SentMessage(_target, msg.sender, _message, nonce, _gasLimit);\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    )\n        public\n        nonReentrant\n        whenNotPaused\n    {\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            _sender,\n            _message,\n            _messageNonce\n        );\n\n        require(\n            _verifyXDomainMessage(\n                xDomainCalldata,\n                _proof\n            ) == 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 == 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(\n            abi.encodePacked(\n                xDomainCalldata,\n                msg.sender,\n                block.number\n            )\n        );\n        relayedMessages[relayId] = true;\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 _gasLimit\n    )\n        public\n    {\n        // Verify that the message is in the queue:\n        address canonicalTransactionChain = resolve(\"CanonicalTransactionChain\");\n        Lib_OVMCodec.QueueElement memory element =\n            ICanonicalTransactionChain(canonicalTransactionChain).getQueueElement(_queueIndex);\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                _gasLimit,\n                _message\n            )\n        );\n\n        require(\n            transactionHash == element.transactionHash,\n            \"Provided message has not been enqueued.\"\n        );\n\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            _sender,\n            _message,\n            _queueIndex\n        );\n\n        _sendXDomainMessage(\n            canonicalTransactionChain,\n            xDomainCalldata,\n            _gasLimit\n        );\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    )\n        internal\n        view\n        returns (\n            bool\n        )\n    {\n        return (\n            _verifyStateRootProof(_proof)\n            && _verifyStorageProof(_xDomainCalldata, _proof)\n        );\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(\n        L2MessageInclusionProof memory _proof\n    )\n        internal\n        view\n        returns (\n            bool\n        )\n    {\n        IStateCommitmentChain ovmStateCommitmentChain = IStateCommitmentChain(\n            resolve(\"StateCommitmentChain\")\n        );\n\n        return (\n            ovmStateCommitmentChain.insideFraudProofWindow(_proof.stateRootBatchHeader) == false\n            && ovmStateCommitmentChain.verifyStateCommitment(\n                _proof.stateRoot,\n                _proof.stateRootBatchHeader,\n                _proof.stateRootProof\n            )\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    )\n        internal\n        view\n        returns (\n            bool\n        )\n    {\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        (\n            bool exists,\n            bytes memory encodedMessagePassingAccount\n        ) = 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 == true,\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 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    )\n        internal\n    {\n        ICanonicalTransactionChain(_canonicalTransactionChain).enqueue(\n            Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,\n            _gasLimit,\n            _message\n        );\n    }\n}\n"
    },
    "contracts/standards/AddressAliasHelper.sol": {
      "content": "\n// 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    /*************\n     * Variables *\n     *************/\n\n    Lib_AddressManager public libAddressManager;\n\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Lib_AddressManager.\n     */\n    constructor(\n        address _libAddressManager\n    ) {\n        libAddressManager = Lib_AddressManager(_libAddressManager);\n    }\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(\n        string memory _name\n    )\n        public\n        view\n        returns (\n            address\n        )\n    {\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    /**********\n     * Events *\n     **********/\n\n    event AddressSet(\n        string indexed _name,\n        address _newAddress,\n        address _oldAddress\n    );\n\n\n    /*************\n     * Variables *\n     *************/\n\n    mapping (bytes32 => address) private addresses;\n\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(\n        string memory _name,\n        address _address\n    )\n        external\n        onlyOwner\n    {\n        bytes32 nameHash = _getNameHash(_name);\n        address oldAddress = addresses[nameHash];\n        addresses[nameHash] = _address;\n\n        emit AddressSet(\n            _name,\n            _address,\n            oldAddress\n        );\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(\n        string memory _name\n    )\n        external\n        view\n        returns (\n            address\n        )\n    {\n        return addresses[_getNameHash(_name)];\n    }\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(\n        string memory _name\n    )\n        internal\n        pure\n        returns (\n            bytes32\n        )\n    {\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    /**********************\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    )\n        internal\n        pure\n        returns (\n            bool _verified\n        )\n    {\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    )\n        internal\n        pure\n        returns (\n            bytes32 _updatedRoot\n        )\n    {\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    )\n        internal\n        pure\n        returns (\n            bool _exists,\n            bytes memory _value\n        )\n    {\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(\n        bytes memory _key,\n        bytes memory _value\n    )\n        internal\n        pure\n        returns (\n            bytes32 _updatedRoot\n        )\n    {\n        bytes memory key = _getSecureKey(_key);\n        return Lib_MerkleTrie.getSingleNodeRootHash(key, _value);\n    }\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(\n        bytes memory _key\n    )\n        private\n        pure\n        returns (\n            bytes memory _secureKey\n        )\n    {\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\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}\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    // solhint-disable max-line-length\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 payable internal constant OVM_ETH = payable(0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000);\n    // solhint-disable-next-line max-line-length\n    address internal constant L2_CROSS_DOMAIN_MESSENGER = 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 internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n    address internal constant L2_STANDARD_TOKEN_FACTORY = 0x4200000000000000000000000000000000000012;\n    address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\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    )\n        internal\n        pure\n        returns (\n            bytes memory\n        )\n    {\n        return abi.encodeWithSignature(\n            \"relayMessage(address,address,bytes,uint256)\",\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    /**********\n     * Events *\n     **********/\n\n    event TransactionEnqueued(\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 _startingQueueIndex,\n        uint256 _numQueueElements,\n        uint256 _totalElements\n    );\n\n    event SequencerBatchAppended(\n        uint256 _startingQueueIndex,\n        uint256 _numQueueElements,\n        uint256 _totalElements\n    );\n\n    event TransactionBatchAppended(\n        uint256 indexed _batchIndex,\n        bytes32 _batchRoot,\n        uint256 _batchSize,\n        uint256 _prevTotalElements,\n        bytes _extraData\n    );\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    /********************\n     * Public Functions *\n     ********************/\n\n\n    /**\n     * Accesses the batch storage container.\n     * @return Reference to the batch storage container.\n     */\n    function batches()\n        external\n        view\n        returns (\n            IChainStorageContainer\n        );\n\n    /**\n     * Accesses the queue storage container.\n     * @return Reference to the queue storage container.\n     */\n    function queue()\n        external\n        view\n        returns (\n            IChainStorageContainer\n        );\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElements()\n        external\n        view\n        returns (\n            uint256 _totalElements\n        );\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatches()\n        external\n        view\n        returns (\n            uint256 _totalBatches\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()\n        external\n        view\n        returns (\n            uint40\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(\n        uint256 _index\n    )\n        external\n        view\n        returns (\n            Lib_OVMCodec.QueueElement memory _element\n        );\n\n    /**\n     * Returns the timestamp of the last transaction.\n     * @return Timestamp for the last transaction.\n     */\n    function getLastTimestamp()\n        external\n        view\n        returns (\n            uint40\n        );\n\n    /**\n     * Returns the blocknumber of the last transaction.\n     * @return Blocknumber for the last transaction.\n     */\n    function getLastBlockNumber()\n        external\n        view\n        returns (\n            uint40\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()\n        external\n        view\n        returns (\n            uint40\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()\n        external\n        view\n        returns (\n            uint40\n        );\n\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    )\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    )\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\";\n\n/**\n * @title IStateCommitmentChain\n */\ninterface IStateCommitmentChain {\n\n    /**********\n     * Events *\n     **********/\n\n    event StateBatchAppended(\n        uint256 indexed _batchIndex,\n        bytes32 _batchRoot,\n        uint256 _batchSize,\n        uint256 _prevTotalElements,\n        bytes _extraData\n    );\n\n    event StateBatchDeleted(\n        uint256 indexed _batchIndex,\n        bytes32 _batchRoot\n    );\n\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElements()\n        external\n        view\n        returns (\n            uint256 _totalElements\n        );\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatches()\n        external\n        view\n        returns (\n            uint256 _totalBatches\n        );\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()\n        external\n        view\n        returns (\n            uint256 _lastSequencerTimestamp\n        );\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(\n        bytes32[] calldata _batch,\n        uint256 _shouldStartAtElement\n    )\n        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(\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    )\n        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    )\n        external\n        view\n        returns (\n            bool _verified\n        );\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(\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    )\n        external\n        view\n        returns (\n            bool _inside\n        );\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    /*******************\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    /**********************\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 constant internal KECCAK256_RLP_NULL_BYTES = keccak256(RLP_NULL_BYTES);\n\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    )\n        internal\n        pure\n        returns (\n            bool _verified\n        )\n    {\n        (\n            bool exists,\n            bytes memory value\n        ) = get(_key, _proof, _root);\n\n        return (\n            exists && Lib_BytesUtils.equal(_value, value)\n        );\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    )\n        internal\n        pure\n        returns (\n            bytes32 _updatedRoot\n        )\n    {\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    )\n        internal\n        pure\n        returns (\n            bool _exists,\n            bytes memory _value\n        )\n    {\n        TrieNode[] memory proof = _parseProof(_proof);\n        (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) =\n            _walkNodePath(proof, _key, _root);\n\n        bool exists = keyRemainder.length == 0;\n\n        require(\n            exists || isFinalNode,\n            \"Provided proof is invalid.\"\n        );\n\n        bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes(\"\");\n\n        return (\n            exists,\n            value\n        );\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(\n        bytes memory _key,\n        bytes memory _value\n    )\n        internal\n        pure\n        returns (\n            bytes32 _updatedRoot\n        )\n    {\n        return keccak256(_makeLeafNode(\n            Lib_BytesUtils.toNibbles(_key),\n            _value\n        ).encoded);\n    }\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(\n                    keccak256(currentNode.encoded) == currentNodeID,\n                    \"Invalid root hash\"\n                );\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    )\n        private\n        pure\n        returns (\n            TrieNode[] memory _newPath\n        )\n    {\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                ) == _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] =\n                    _makeLeafNode(Lib_BytesUtils.slice(keyRemainder, 1), _value);\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 =\n                        _makeLeafNode(lastNodeKey, _getNodeValue(lastNode));\n                    newBranch =\n                        _editBranchIndex(\n                                newBranch,\n                                branchKey,\n                                _getNodeHash(modifiedLastNode.encoded));\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 =\n                        _makeExtensionNode(lastNodeKey, _getNodeValue(lastNode));\n                    newBranch =\n                        _editBranchIndex(\n                            newBranch,\n                            branchKey,\n                            _getNodeHash(modifiedLastNode.encoded));\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(\n        TrieNode[] memory _nodes,\n        bytes memory _key\n    )\n        private\n        pure\n        returns (\n            bytes32 _updatedRoot\n        )\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(\n        bytes memory _proof\n    )\n        private\n        pure\n        returns (\n            TrieNode[] memory _parsed\n        )\n    {\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({\n                encoded: encoded,\n                decoded: Lib_RLPReader.readList(encoded)\n            });\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(\n        Lib_RLPReader.RLPItem memory _node\n    )\n        private\n        pure\n        returns (\n            bytes32 _nodeID\n        )\n    {\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(\n        TrieNode memory _node\n    )\n        private\n        pure\n        returns (\n            bytes memory _path\n        )\n    {\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(\n        TrieNode memory _node\n    )\n        private\n        pure\n        returns (\n            bytes memory _key\n        )\n    {\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(\n        TrieNode memory _node\n    )\n        private\n        pure\n        returns (\n            bytes memory _value\n        )\n    {\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(\n        bytes memory _encoded\n    )\n        private\n        pure\n        returns (\n            bytes memory _hash\n        )\n    {\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(\n        TrieNode memory _node\n    )\n        private\n        pure\n        returns (\n            NodeType _type\n        )\n    {\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(\n        bytes memory _a,\n        bytes memory _b\n    )\n        private\n        pure\n        returns (\n            uint256 _shared\n        )\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(\n        bytes[] memory _raw\n    )\n        private\n        pure\n        returns (\n            TrieNode memory _node\n        )\n    {\n        bytes memory encoded = Lib_RLPWriter.writeList(_raw);\n\n        return TrieNode({\n            encoded: encoded,\n            decoded: Lib_RLPReader.readList(encoded)\n        });\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(\n        Lib_RLPReader.RLPItem[] memory _items\n    )\n        private\n        pure\n        returns (\n            TrieNode memory _node\n        )\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(\n        bytes memory _key,\n        bytes memory _value\n    )\n        private\n        pure\n        returns (\n            TrieNode memory _node\n        )\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(\n        TrieNode memory _node,\n        bytes memory _value\n    )\n        private\n        pure\n        returns (\n            TrieNode memory\n        )\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(\n        bytes memory _key,\n        bytes memory _value\n    )\n        private\n        pure\n        returns (\n            TrieNode memory _node\n        )\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()\n        private\n        pure\n        returns (\n            TrieNode memory _node\n        )\n    {\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(\n        TrieNode memory _branch,\n        bytes memory _value\n    )\n        private\n        pure\n        returns (\n            TrieNode memory _updatedNode\n        )\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    )\n        private\n        pure\n        returns (\n            TrieNode memory _updatedNode\n        )\n    {\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(\n        bytes memory _key,\n        bool _isLeaf\n    )\n        private\n        pure\n        returns (\n            bytes memory _prefixedKey\n        )\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(\n        bytes memory _path\n    )\n        private\n        pure\n        returns (\n            bytes memory _unprefixedKey\n        )\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    )\n        private\n        pure\n        returns (\n            TrieNode[] memory _joined\n        )\n    {\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/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    /********************\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(\n        bytes27 _globalMetadata\n    )\n        external;\n\n    /**\n     * Retrieves the container's global metadata field.\n     * @return Container global metadata field.\n     */\n    function getGlobalMetadata()\n        external\n        view\n        returns (\n            bytes27\n        );\n\n    /**\n     * Retrieves the number of objects stored in the container.\n     * @return Number of objects in the container.\n     */\n    function length()\n        external\n        view\n        returns (\n            uint256\n        );\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(\n        bytes32 _object\n    )\n        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(\n        bytes32 _object,\n        bytes27 _globalMetadata\n    )\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(\n        uint256 _index\n    )\n        external\n        view\n        returns (\n            bytes32\n        );\n\n    /**\n     * Removes all objects after and including a given index.\n     * @param _index Object index to delete from.\n     */\n    function deleteElementsAfterInclusive(\n        uint256 _index\n    )\n        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(\n        uint256 _index,\n        bytes27 _globalMetadata\n    )\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/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\";\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    /*************\n     * Constants *\n     *************/\n\n    uint256 public FRAUD_PROOF_WINDOW;\n    uint256 public SEQUENCER_PUBLISH_WINDOW;\n\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    )\n        Lib_AddressResolver(_libAddressManager)\n    {\n        FRAUD_PROOF_WINDOW = _fraudProofWindow;\n        SEQUENCER_PUBLISH_WINDOW = _sequencerPublishWindow;\n    }\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()\n        public\n        view\n        returns (\n            IChainStorageContainer\n        )\n    {\n        return IChainStorageContainer(\n            resolve(\"ChainStorageContainer-SCC-batches\")\n        );\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalElements()\n        public\n        view\n        returns (\n            uint256 _totalElements\n        )\n    {\n        (uint40 totalElements, ) = _getBatchExtraData();\n        return uint256(totalElements);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalBatches()\n        public\n        view\n        returns (\n            uint256 _totalBatches\n        )\n    {\n        return batches().length();\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getLastSequencerTimestamp()\n        public\n        view\n        returns (\n            uint256 _lastSequencerTimestamp\n        )\n    {\n        (, uint40 lastSequencerTimestamp) = _getBatchExtraData();\n        return uint256(lastSequencerTimestamp);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function appendStateBatch(\n        bytes32[] memory _batch,\n        uint256 _shouldStartAtElement\n    )\n        public\n    {\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 == getTotalElements(),\n            \"Actual batch start index does not match expected start index.\"\n        );\n\n        // Proposers must have previously staked at the BondManager\n        require(\n            IBondManager(resolve(\"BondManager\")).isCollateralized(msg.sender),\n            \"Proposer does not have enough collateral posted\"\n        );\n\n        require(\n            _batch.length > 0,\n            \"Cannot submit an empty state batch.\"\n        );\n\n        require(\n            getTotalElements() + _batch.length <=\n                ICanonicalTransactionChain(resolve(\"CanonicalTransactionChain\"))\n                .getTotalElements(),\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        _appendBatch(\n            _batch,\n            abi.encode(block.timestamp, msg.sender)\n        );\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function deleteStateBatch(\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    )\n        public\n    {\n        require(\n            msg.sender == resolve(\"OVM_FraudVerifier\"),\n            \"State batches can only be deleted by the OVM_FraudVerifier.\"\n        );\n\n        require(\n            _isValidBatchHeader(_batchHeader),\n            \"Invalid batch header.\"\n        );\n\n        require(\n            insideFraudProofWindow(_batchHeader),\n            \"State batches can only be deleted within the fraud proof window.\"\n        );\n\n        _deleteBatch(_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    )\n        public\n        view\n        returns (\n            bool\n        )\n    {\n        require(\n            _isValidBatchHeader(_batchHeader),\n            \"Invalid batch header.\"\n        );\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 insideFraudProofWindow(\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    )\n        public\n        view\n        returns (\n            bool _inside\n        )\n    {\n        (uint256 timestamp,) = abi.decode(\n            _batchHeader.extraData,\n            (uint256, address)\n        );\n\n        require(\n            timestamp != 0,\n            \"Batch header timestamp cannot be zero\"\n        );\n        return (timestamp + FRAUD_PROOF_WINDOW) > block.timestamp;\n    }\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()\n        internal\n        view\n        returns (\n            uint40,\n            uint40\n        )\n    {\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(extraData, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)\n            lastSequencerTimestamp := shr(40, and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000))\n        }\n        // solhint-enable max-line-length\n\n        return (\n            totalElements,\n            lastSequencerTimestamp\n        );\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(\n        uint40 _totalElements,\n        uint40 _lastSequencerTimestamp\n    )\n        internal\n        pure\n        returns (\n            bytes27\n        )\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 _appendBatch(\n        bytes32[] memory _batch,\n        bytes memory _extraData\n    )\n        internal\n    {\n        address sequencer = resolve(\"OVM_Proposer\");\n        (uint40 totalElements, uint40 lastSequencerTimestamp) = _getBatchExtraData();\n\n        if (msg.sender == sequencer) {\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: getTotalBatches(),\n            batchRoot: Lib_MerkleTree.getMerkleRoot(_batch),\n            batchSize: _batch.length,\n            prevTotalElements: totalElements,\n            extraData: _extraData\n        });\n\n        emit StateBatchAppended(\n            batchHeader.batchIndex,\n            batchHeader.batchRoot,\n            batchHeader.batchSize,\n            batchHeader.prevTotalElements,\n            batchHeader.extraData\n        );\n\n        batches().push(\n            Lib_OVMCodec.hashBatchHeader(batchHeader),\n            _makeBatchExtraData(\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 _deleteBatch(\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    )\n        internal\n    {\n        require(\n            _batchHeader.batchIndex < batches().length(),\n            \"Invalid batch index.\"\n        );\n\n        require(\n            _isValidBatchHeader(_batchHeader),\n            \"Invalid batch header.\"\n        );\n\n        batches().deleteElementsAfterInclusive(\n            _batchHeader.batchIndex,\n            _makeBatchExtraData(\n                uint40(_batchHeader.prevTotalElements),\n                0\n            )\n        );\n\n        emit StateBatchDeleted(\n            _batchHeader.batchIndex,\n            _batchHeader.batchRoot\n        );\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 _isValidBatchHeader(\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    )\n        internal\n        view\n        returns (\n            bool\n        )\n    {\n        return Lib_OVMCodec.hashBatchHeader(_batchHeader) == batches().get(_batchHeader.batchIndex);\n    }\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    /**********************\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(\n        bytes32[] memory _elements\n    )\n        internal\n        pure\n        returns (\n            bytes32\n        )\n    {\n        require(\n            _elements.length > 0,\n            \"Lib_MerkleTree: Must provide at least one leaf hash.\"\n        );\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    )\n        internal\n        pure\n        returns (\n            bool\n        )\n    {\n        require(\n            _totalLeaves > 0,\n            \"Lib_MerkleTree: Total leaves must be greater than zero.\"\n        );\n\n        require(\n            _index < _totalLeaves,\n            \"Lib_MerkleTree: Index out of bounds.\"\n        );\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(\n                    abi.encodePacked(\n                        _siblings[i],\n                        computedRoot\n                    )\n                );\n            } else {\n                computedRoot = keccak256(\n                    abi.encodePacked(\n                        computedRoot,\n                        _siblings[i]\n                    )\n                );\n            }\n\n            _index >>= 1;\n        }\n\n        return _root == computedRoot;\n    }\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(\n        uint256 _in\n    )\n        private\n        pure\n        returns (\n            uint256\n        )\n    {\n        require(\n            _in > 0,\n            \"Lib_MerkleTree: Cannot compute ceil(log_2) of 0.\"\n        );\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 & (uint(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 ((uint(1) << highest) != _in) {\n            highest += 1;\n        }\n\n        return highest;\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    /********************\n     * Public Functions *\n     ********************/\n\n    function isCollateralized(\n        address _who\n    ) external view returns (bool);\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 * Three distinct Chain Storage Containers will be deployed on Layer 1:\n * 1. Stores transaction batches for the Canonical Transaction Chain\n * 2. Stores queued transactions for the Canonical Transaction Chain\n * 3. Stores chain state batches for the State Commitment Chain\n *\n * Runtime target: EVM\n */\ncontract ChainStorageContainer is IChainStorageContainer, Lib_AddressResolver {\n\n    /*************\n     * Libraries *\n     *************/\n\n    using Lib_Buffer for Lib_Buffer.Buffer;\n\n\n    /*************\n     * Variables *\n     *************/\n\n    string public owner;\n    Lib_Buffer.Buffer internal buffer;\n\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(\n        address _libAddressManager,\n        string memory _owner\n    )\n        Lib_AddressResolver(_libAddressManager)\n    {\n        owner = _owner;\n    }\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    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function setGlobalMetadata(\n        bytes27 _globalMetadata\n    )\n        public\n        onlyOwner\n    {\n        return buffer.setExtraData(_globalMetadata);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function getGlobalMetadata()\n        public\n        view\n        returns (\n            bytes27\n        )\n    {\n        return buffer.getExtraData();\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function length()\n        public\n        view\n        returns (\n            uint256\n        )\n    {\n        return uint256(buffer.getLength());\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function push(\n        bytes32 _object\n    )\n        public\n        onlyOwner\n    {\n        buffer.push(_object);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function push(\n        bytes32 _object,\n        bytes27 _globalMetadata\n    )\n        public\n        onlyOwner\n    {\n        buffer.push(_object, _globalMetadata);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function get(\n        uint256 _index\n    )\n        public\n        view\n        returns (\n            bytes32\n        )\n    {\n        return buffer.get(uint40(_index));\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function deleteElementsAfterInclusive(\n        uint256 _index\n    )\n        public\n        onlyOwner\n    {\n        buffer.deleteElementsAfterInclusive(\n            uint40(_index)\n        );\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function deleteElementsAfterInclusive(\n        uint256 _index,\n        bytes27 _globalMetadata\n    )\n        public\n        onlyOwner\n    {\n        buffer.deleteElementsAfterInclusive(\n            uint40(_index),\n            _globalMetadata\n        );\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    /*************\n     * Libraries *\n     *************/\n\n    using Lib_Buffer for Buffer;\n\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\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    /**********************\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    )\n        internal\n    {\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(\n        Buffer storage _self,\n        bytes32 _value\n    )\n        internal\n    {\n        BufferContext memory ctx = _self.getContext();\n\n        _self.push(\n            _value,\n            ctx.extraData\n        );\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(\n        Buffer storage _self,\n        uint256 _index\n    )\n        internal\n        view\n        returns (\n            bytes32\n        )\n    {\n        BufferContext memory ctx = _self.getContext();\n\n        require(\n            _index < ctx.length,\n            \"Index out of bounds.\"\n        );\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    )\n        internal\n    {\n        BufferContext memory ctx = _self.getContext();\n\n        require(\n            _index < ctx.length,\n            \"Index out of bounds.\"\n        );\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(\n        Buffer storage _self,\n        uint40 _index\n    )\n        internal\n    {\n        BufferContext memory ctx = _self.getContext();\n        _self.deleteElementsAfterInclusive(\n            _index,\n            ctx.extraData\n        );\n    }\n\n    /**\n     * Retrieves the current global index.\n     * @param _self Buffer to access.\n     * @return Current global index.\n     */\n    function getLength(\n        Buffer storage _self\n    )\n        internal\n        view\n        returns (\n            uint40\n        )\n    {\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(\n        Buffer storage _self,\n        bytes27 _extraData\n    )\n        internal\n    {\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(\n        Buffer storage _self\n    )\n        internal\n        view\n        returns (\n            bytes27\n        )\n    {\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(\n        Buffer storage _self,\n        BufferContext memory _ctx\n    )\n        internal\n    {\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(\n        Buffer storage _self\n    )\n        internal\n        view\n        returns (\n            BufferContext memory\n        )\n    {\n        bytes32 context = _self.context;\n        uint40 length;\n        bytes27 extraData;\n        assembly {\n            // solhint-disable-next-line max-line-length\n            length    := and(context, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)\n            // solhint-disable-next-line max-line-length\n            extraData := and(context, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)\n        }\n\n        return BufferContext({\n            length: length,\n            extraData: extraData\n        });\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\";\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    /**\n     * @param _libAddressManager Address of the Address Manager.\n     */\n    constructor(\n        address _libAddressManager\n    )\n        Lib_AddressResolver(_libAddressManager)\n    {}\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(\n        address _who\n    )\n        public\n        view\n        returns (\n            bool\n        )\n    {\n        // Only authenticate sequencer to submit state root batches.\n        return _who == resolve(\"OVM_Proposer\");\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\";\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 also allows any account to 'enqueue' an L2 transaction, which will require that the\n * Sequencer will eventually append it to the rollup state.\n *\n * Runtime target: EVM\n */\ncontract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressResolver {\n\n    /*************\n     * Constants *\n     *************/\n\n    // L2 tx gas-related\n    uint256 constant public MIN_ROLLUP_TX_GAS = 100000;\n    uint256 constant public MAX_ROLLUP_TX_SIZE = 50000;\n    uint256 immutable public L2_GAS_DISCOUNT_DIVISOR;\n    uint256 immutable public ENQUEUE_GAS_COST;\n    uint256 immutable public ENQUEUE_L2_GAS_PREPAID;\n\n    // Encoding-related (all in bytes)\n    uint256 constant internal BATCH_CONTEXT_SIZE = 16;\n    uint256 constant internal BATCH_CONTEXT_LENGTH_POS = 12;\n    uint256 constant internal BATCH_CONTEXT_START_POS = 15;\n    uint256 constant internal TX_DATA_HEADER_SIZE = 3;\n    uint256 constant internal BYTES_TILL_TX_DATA = 65;\n\n\n    /*************\n     * Variables *\n     *************/\n\n    uint256 public maxTransactionGasLimit;\n\n\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor(\n        address _libAddressManager,\n        uint256 _maxTransactionGasLimit,\n        uint256 _l2GasDiscountDivisor,\n        uint256 _enqueueGasCost\n    )\n        Lib_AddressResolver(_libAddressManager)\n    {\n        maxTransactionGasLimit = _maxTransactionGasLimit;\n        L2_GAS_DISCOUNT_DIVISOR = _l2GasDiscountDivisor;\n        ENQUEUE_GAS_COST  = _enqueueGasCost;\n        ENQUEUE_L2_GAS_PREPAID = _l2GasDiscountDivisor * _enqueueGasCost;\n    }\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()\n        public\n        view\n        returns (\n            IChainStorageContainer\n        )\n    {\n        return IChainStorageContainer(\n            resolve(\"ChainStorageContainer-CTC-batches\")\n        );\n    }\n\n    /**\n     * Accesses the queue storage container.\n     * @return Reference to the queue storage container.\n     */\n    function queue()\n        public\n        view\n        returns (\n            IChainStorageContainer\n        )\n    {\n        return IChainStorageContainer(\n            resolve(\"ChainStorageContainer-CTC-queue\")\n        );\n    }\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElements()\n        public\n        view\n        returns (\n            uint256 _totalElements\n        )\n    {\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()\n        public\n        view\n        returns (\n            uint256 _totalBatches\n        )\n    {\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()\n        public\n        view\n        returns (\n            uint40\n        )\n    {\n        (,uint40 nextQueueIndex,,) = _getBatchExtraData();\n        return nextQueueIndex;\n    }\n\n    /**\n     * Returns the timestamp of the last transaction.\n     * @return Timestamp for the last transaction.\n     */\n    function getLastTimestamp()\n        public\n        view\n        returns (\n            uint40\n        )\n    {\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()\n        public\n        view\n        returns (\n            uint40\n        )\n    {\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(\n        uint256 _index\n    )\n        public\n        view\n        returns (\n            Lib_OVMCodec.QueueElement memory _element\n        )\n    {\n        return _getQueueElement(\n            _index,\n            queue()\n        );\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()\n        public\n        view\n        returns (\n            uint40\n        )\n    {\n        return getQueueLength() - getNextQueueIndex();\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()\n        public\n        view\n        returns (\n            uint40\n        )\n    {\n        return _getQueueLength(\n            queue()\n        );\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    )\n        external\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(\n            _gasLimit >= MIN_ROLLUP_TX_GAS,\n            \"Transaction gas limit too low to enqueue.\"\n        );\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. Therefore, we define 'ENQUEUE_L2_GAS_PREPAID' as a\n        // threshold. If the _gasLimit for the enqueued transaction is above this threshold, then we\n        // 'charge' to user by burning additional L1 gas. Since gas is cheaper on L2 than L1, we\n        // only need to burn a fraction of the provided L1 gas, which is determined by the\n        // L2_GAS_DISCOUNT_DIVISOR.\n        if(_gasLimit > ENQUEUE_L2_GAS_PREPAID) {\n            uint256 gasToConsume = (_gasLimit - ENQUEUE_L2_GAS_PREPAID) / L2_GAS_DISCOUNT_DIVISOR;\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(\n                startingGas > gasToConsume,\n                \"Insufficient gas for L2 rate limiting burn.\"\n            );\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(\n            abi.encode(\n                sender,\n                _target,\n                _gasLimit,\n                _data\n            )\n        );\n\n        bytes32 timestampAndBlockNumber;\n        assembly {\n            timestampAndBlockNumber := timestamp()\n            timestampAndBlockNumber := or(timestampAndBlockNumber, shl(40, number()))\n        }\n\n        IChainStorageContainer queueRef = queue();\n\n        queueRef.push(transactionHash);\n        queueRef.push(timestampAndBlockNumber);\n\n        // The underlying queue data structure stores 2 elements\n        // per insertion, so to get the real queue length we need\n        // to divide by 2 and subtract 1.\n        uint256 queueIndex = queueRef.length() / 2 - 1;\n        emit TransactionEnqueued(\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 appendSequencerBatch()\n        external\n    {\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(\"OVM_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(\n            msg.data.length >= nextTransactionPtr,\n            \"Not enough BatchContexts provided.\"\n        );\n\n        // Take a reference to the queue and its length so we don't have to keep resolving it.\n        // Length isn't going to change during the course of execution, so it's fine to simply\n        // resolve this once at the start. Saves gas.\n        IChainStorageContainer queueRef = queue();\n        uint40 queueLength = _getQueueLength(queueRef);\n\n        // Counter for number of sequencer transactions appended so far.\n        uint32 numSequencerTransactions = 0;\n\n        // We will sequentially append leaves which are pointers to the queue.\n        // The initial queue index is what is currently in storage.\n        uint40 nextQueueIndex = getNextQueueIndex();\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 <= queueLength,\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 = _getQueueElement(\n                nextQueueIndex - 1,\n                queueRef\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            nextQueueIndex - numQueuedTransactions,\n            numQueuedTransactions,\n            getTotalElements()\n        );\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(\n        uint256 _index\n    )\n        internal\n        pure\n        returns (\n            BatchContext memory\n        )\n    {\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 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(extraData, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)\n            nextQueueIndex  :=  shr(40, and(extraData, 0x00000000000000000000000000000000000000000000FFFFFFFFFF0000000000))\n            lastTimestamp   :=  shr(80, and(extraData, 0x0000000000000000000000000000000000FFFFFFFFFF00000000000000000000))\n            lastBlockNumber :=  shr(120, and(extraData, 0x000000000000000000000000FFFFFFFFFF000000000000000000000000000000))\n        }\n        // solhint-enable max-line-length\n\n        return (\n            totalElements,\n            nextQueueIndex,\n            lastTimestamp,\n            lastBlockNumber\n        );\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _nextQueueIndex 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 _nextQueueIndex,\n        uint40 _timestamp,\n        uint40 _blockNumber\n    )\n        internal\n        pure\n        returns (\n            bytes27\n        )\n    {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _nextQueueIndex))\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     * 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(\n        uint256 _index,\n        IChainStorageContainer _queueRef\n    )\n        internal\n        view\n        returns (\n            Lib_OVMCodec.QueueElement memory _element\n        )\n    {\n        // The underlying queue data structure stores 2 elements\n        // per insertion, so to get the actual desired queue index\n        // we need to multiply by 2.\n        uint40 trueIndex = uint40(_index * 2);\n        bytes32 transactionHash = _queueRef.get(trueIndex);\n        bytes32 timestampAndBlockNumber = _queueRef.get(trueIndex + 1);\n\n        uint40 elementTimestamp;\n        uint40 elementBlockNumber;\n        // solhint-disable max-line-length\n        assembly {\n            elementTimestamp   :=         and(timestampAndBlockNumber, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)\n            elementBlockNumber := shr(40, and(timestampAndBlockNumber, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000))\n        }\n        // solhint-enable max-line-length\n\n        return Lib_OVMCodec.QueueElement({\n            transactionHash: transactionHash,\n            timestamp: elementTimestamp,\n            blockNumber: elementBlockNumber\n        });\n    }\n\n    /**\n     * Retrieves the length of the queue.\n     * @return Length of the queue.\n     */\n    function _getQueueLength(\n        IChainStorageContainer _queueRef\n    )\n        internal\n        view\n        returns (\n            uint40\n        )\n    {\n        // The underlying queue data structure stores 2 elements\n        // per insertion, so to get the real queue length we need\n        // to divide by 2.\n        return uint40(_queueRef.length() / 2);\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    )\n        internal\n    {\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            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\n    /**\n     * Hashes a transaction chain element.\n     * @param _element Chain element to hash.\n     * @return Hash of the chain element.\n     */\n    function _hashTransactionChainElement(\n        Lib_OVMCodec.TransactionChainElement memory _element\n    )\n        internal\n        pure\n        returns (\n            bytes32\n        )\n    {\n        return keccak256(\n            abi.encode(\n                _element.isSequenced,\n                _element.queueIndex,\n                _element.timestamp,\n                _element.blockNumber,\n                _element.txData\n            )\n        );\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(\n        Lib_OVMCodec.Transaction memory _transaction\n    )\n        public\n        pure\n        returns (\n            bytes memory _encoded\n        )\n    {\n        return Lib_OVMCodec.encodeTransaction(_transaction);\n    }\n\n    function hashTransaction(\n        Lib_OVMCodec.Transaction memory _transaction\n    )\n        public\n        pure\n        returns (\n            bytes32 _hash\n        )\n    {\n        return Lib_OVMCodec.hashTransaction(_transaction);\n    }\n}\n"
    },
    "contracts/test-libraries/utils/TestLib_Bytes32Utils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_Bytes32Utils } from \"../../libraries/utils/Lib_Bytes32Utils.sol\";\n\n/**\n * @title TestLib_Byte32Utils\n */\ncontract TestLib_Bytes32Utils {\n\n    function toBool(\n        bytes32 _in\n    )\n        public\n        pure\n        returns (\n            bool _out\n        )\n    {\n        return Lib_Bytes32Utils.toBool(_in);\n    }\n\n    function fromBool(\n        bool _in\n    )\n        public\n        pure\n        returns (\n            bytes32 _out\n        )\n    {\n        return Lib_Bytes32Utils.fromBool(_in);\n    }\n\n    function toAddress(\n        bytes32 _in\n    )\n        public\n        pure\n        returns (\n            address _out\n        )\n    {\n        return Lib_Bytes32Utils.toAddress(_in);\n    }\n\n    function fromAddress(\n        address _in\n    )\n        public\n        pure\n        returns (\n            bytes32 _out\n        )\n    {\n        return Lib_Bytes32Utils.fromAddress(_in);\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\n    function concat(\n        bytes memory _preBytes,\n        bytes memory _postBytes\n    )\n        public\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(\n            _preBytes,\n            _postBytes\n        );\n    }\n\n    function slice(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    )\n        public\n        pure\n        returns (bytes memory)\n    {\n        return Lib_BytesUtils.slice(\n            _bytes,\n            _start,\n            _length\n        );\n    }\n\n    function toBytes32(\n        bytes memory _bytes\n    )\n        public\n        pure\n        returns (bytes32)\n    {\n        return Lib_BytesUtils.toBytes32(\n            _bytes\n        );\n    }\n\n    function toUint256(\n        bytes memory _bytes\n    )\n        public\n        pure\n        returns (uint256)\n    {\n        return Lib_BytesUtils.toUint256(\n            _bytes\n        );\n    }\n\n    function toNibbles(\n        bytes memory _bytes\n    )\n        public\n        pure\n        returns (bytes memory)\n    {\n        return Lib_BytesUtils.toNibbles(\n            _bytes\n        );\n    }\n\n    function fromNibbles(\n        bytes memory _bytes\n    )\n        public\n        pure\n        returns (bytes memory)\n    {\n        return Lib_BytesUtils.fromNibbles(\n            _bytes\n        );\n    }\n\n    function equal(\n        bytes memory _bytes,\n        bytes memory _other\n    )\n        public\n        pure\n        returns (bool)\n    {\n        return Lib_BytesUtils.equal(\n            _bytes,\n            _other\n        );\n    }\n\n    function sliceWithTaintedMemory(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    )\n        public\n        returns (bytes memory)\n    {\n        new TestERC20();\n        return Lib_BytesUtils.slice(\n            _bytes,\n            _start,\n            _length\n        );\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 => uint) public balanceOf;\n    mapping(address => mapping(address => uint)) 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(address owner, address spender, uint256 value) private {\n        allowance[owner][spender] = value;\n        emit Approval(owner, spender, value);\n    }\n\n    function _transfer(address from, address to, uint256 value) 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(address from, address to, uint256 value) external returns (bool) {\n        if (allowance[from][msg.sender] != type(uint).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/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\n    function writeBytes(\n        bytes memory _in\n    )\n        public\n        pure\n        returns (\n            bytes memory _out\n        )\n    {\n        return Lib_RLPWriter.writeBytes(_in);\n    }\n\n    function writeList(\n        bytes[] memory _in\n    )\n        public\n        pure\n        returns (\n            bytes memory _out\n        )\n    {\n        return Lib_RLPWriter.writeList(_in);\n    }\n\n    function writeString(\n        string memory _in\n    )\n        public\n        pure\n        returns (\n            bytes memory _out\n        )\n    {\n        return Lib_RLPWriter.writeString(_in);\n    }\n\n    function writeAddress(\n        address _in\n    )\n        public\n        pure\n        returns (\n            bytes memory _out\n        )\n    {\n        return Lib_RLPWriter.writeAddress(_in);\n    }\n\n    function writeUint(\n        uint256 _in\n    )\n        public\n        pure\n        returns (\n            bytes memory _out\n        )\n    {\n        return Lib_RLPWriter.writeUint(_in);\n    }\n\n    function writeBool(\n        bool _in\n    )\n        public\n        pure\n        returns (\n            bytes memory _out\n        )\n    {\n        return Lib_RLPWriter.writeBool(_in);\n    }\n\n    function writeAddressWithTaintedMemory(\n        address _in\n    )\n        public\n        returns (\n            bytes memory _out\n        )\n    {\n        new TestERC20();\n        return Lib_RLPWriter.writeAddress(_in);\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\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    )\n        public\n        pure\n        returns (\n            bool\n        )\n    {\n        return Lib_MerkleTrie.verifyInclusionProof(\n            _key,\n            _value,\n            _proof,\n            _root\n        );\n    }\n\n    function update(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    )\n        public\n        pure\n        returns (\n            bytes32\n        )\n    {\n        return Lib_MerkleTrie.update(\n            _key,\n            _value,\n            _proof,\n            _root\n        );\n    }\n\n    function get(\n        bytes memory _key,\n        bytes memory _proof,\n        bytes32 _root\n    )\n        public\n        pure\n        returns (\n            bool,\n            bytes memory\n        )\n    {\n        return Lib_MerkleTrie.get(\n            _key,\n            _proof,\n            _root\n        );\n    }\n\n    function getSingleNodeRootHash(\n        bytes memory _key,\n        bytes memory _value\n    )\n        public\n        pure\n        returns (\n            bytes32\n        )\n    {\n        return Lib_MerkleTrie.getSingleNodeRootHash(\n            _key,\n            _value\n        );\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\n    function readList(\n        bytes memory _in\n    )\n        public\n        pure\n        returns (\n            bytes[] memory\n        )\n    {\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(\n        bytes memory _in\n    )\n        public\n        pure\n        returns (\n            string memory\n        )\n    {\n        return Lib_RLPReader.readString(_in);\n    }\n\n    function readBytes(\n        bytes memory _in\n    )\n        public\n        pure\n        returns (\n            bytes memory\n        )\n    {\n        return Lib_RLPReader.readBytes(_in);\n    }\n\n    function readBytes32(\n        bytes memory _in\n    )\n        public\n        pure\n        returns (\n            bytes32\n        )\n    {\n        return Lib_RLPReader.readBytes32(_in);\n    }\n\n    function readUint256(\n        bytes memory _in\n    )\n        public\n        pure\n        returns (\n            uint256\n        )\n    {\n        return Lib_RLPReader.readUint256(_in);\n    }\n\n    function readBool(\n        bytes memory _in\n    )\n        public\n        pure\n        returns (\n            bool\n        )\n    {\n        return Lib_RLPReader.readBool(_in);\n    }\n\n    function readAddress(\n        bytes memory _in\n    )\n        public\n        pure\n        returns (\n            address\n        )\n    {\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\";\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\n    IL2CrossDomainMessenger\n{\n\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    /***************\n     * Constructor *\n     ***************/\n\n    constructor(\n        address _l1CrossDomainMessenger\n    ) {\n        l1CrossDomainMessenger = _l1CrossDomainMessenger;\n    }\n\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function xDomainMessageSender()\n        public\n        view\n        returns (\n            address\n        )\n    {\n        require(xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER, \"xDomainMessageSender is not set\");\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    )\n        public\n    {\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        // Actually send the message.\n        iOVM_L2ToL1MessagePasser(\n            Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER\n        ).passMessageToL1(xDomainCalldata);\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);\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    )\n        public\n    {\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(\n            abi.encodePacked(\n                xDomainCalldata,\n                msg.sender,\n                block.number\n            )\n        );\n\n        relayedMessages[relayId] = true;\n    }\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    /********************\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    /**********\n     * Events *\n     **********/\n\n    event L2ToL1Message(\n        uint256 _nonce,\n        address _sender,\n        bytes _data\n    );\n\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function passMessageToL1(bytes calldata _message) external;\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 */\ncontract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {\n\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(\n        bytes memory _message\n    )\n        public\n    {\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(\n            abi.encodePacked(\n                _message,\n                msg.sender\n            )\n        )] = true;\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    /*************\n     * Variables *\n     *************/\n\n    // Messenger contract used to send and recieve messages from the other domain.\n    address public messenger;\n\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _messenger Address of the CrossDomainMessenger on the current layer.\n     */\n    constructor(\n        address _messenger\n    ) {\n        messenger = _messenger;\n    }\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(\n        address _sourceDomainAccount\n    ) {\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    /**********************\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()\n        internal\n        virtual\n        returns (\n            ICrossDomainMessenger\n        )\n    {\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    )\n        internal\n    {\n        getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);\n    }\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\";\n\n/* Contract Imports */\nimport { IL2StandardERC20 } from \"../../standards/IL2StandardERC20.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    /********************************\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(\n        address _l2CrossDomainMessenger,\n        address _l1TokenBridge\n    )\n        CrossDomainEnabled(_l2CrossDomainMessenger)\n    {\n        l1TokenBridge = _l1TokenBridge;\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    )\n        external\n        virtual\n    {\n        _initiateWithdrawal(\n            _l2Token,\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    )\n        external\n        virtual\n    {\n        _initiateWithdrawal(\n            _l2Token,\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    )\n        internal\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.finalizeETHWithdrawal.selector,\n                        _from,\n                        _to,\n                        _amount,\n                        _data\n                    );\n        } else {\n            message = abi.encodeWithSelector(\n                        IL1ERC20Bridge.finalizeERC20Withdrawal.selector,\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        );\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    )\n        external\n        virtual\n        onlyFromCrossDomainAccount(l1TokenBridge)\n    {\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            // 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                IL1ERC20Bridge.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            );\n            emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data);\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    /**********\n     * Events *\n     **********/\n    event ETHDepositInitiated (\n        address indexed _from,\n        address indexed _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    event ETHWithdrawalFinalized (\n        address indexed _from,\n        address indexed _to,\n        uint256 _amount,\n        bytes _data\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 (\n        uint32 _l2Gas,\n        bytes calldata _data\n    )\n        external\n        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    )\n        external\n        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        uint _amount,\n        bytes calldata _data\n    )\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    /**********\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    /********************\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        uint _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    )\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        uint _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    )\n        external;\n\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        uint _amount,\n        bytes calldata _data\n    )\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    /**********\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    /********************\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        uint _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    )\n        external;\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        uint _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    )\n        external;\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        uint _amount,\n        bytes calldata _data\n    )\n        external;\n\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"
    },
    "@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"
    },
    "@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/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\";\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 {\n\n    /*************\n     * Constants *\n     *************/\n\n    // Minimum ETH balance that can be withdrawn in a single withdrawal.\n    uint256 public constant MIN_WITHDRAWAL_AMOUNT = 15 ether;\n\n\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\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 _l1FeeWallet\n    ) {\n        l1FeeWallet = _l1FeeWallet;\n    }\n\n\n    /************\n     * Fallback *\n     ************/\n\n    receive() external payable {}\n\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function withdraw()\n        public\n    {\n        require(\n            address(this).balance >= MIN_WITHDRAWAL_AMOUNT,\n            // solhint-disable-next-line max-line-length\n            \"OVM_SequencerFeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n        );\n\n        L2StandardBridge(Lib_PredeployAddresses.L2_STANDARD_BRIDGE).withdrawTo(\n            Lib_PredeployAddresses.OVM_ETH,\n            l1FeeWallet,\n            address(this).balance,\n            0,\n            bytes(\"\")\n        );\n    }\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    /***************\n     * Constructor *\n     ***************/\n\n    constructor()\n        L2StandardERC20(\n            Lib_PredeployAddresses.L2_STANDARD_BRIDGE,\n            address(0),\n            \"Ether\",\n            \"ETH\"\n        )\n    {}\n\n\n    // ETH ERC20 features are disabled until further notice.\n    // Discussion here: https://github.com/ethereum-optimism/optimism/discussions/1444\n\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n        revert(\"OVM_ETH: transfer is disabled pending further community discussion.\");\n    }\n\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        revert(\"OVM_ETH: approve is disabled pending further community discussion.\");\n    }\n\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n        revert(\"OVM_ETH: transferFrom is disabled pending further community discussion.\");\n    }\n\n    function increaseAllowance(address spender, uint256 addedValue) public virtual override returns (bool) {\n        revert(\"OVM_ETH: increaseAllowance is disabled pending further community discussion.\");\n    }\n\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual override returns (bool) {\n        revert(\"OVM_ETH: decreaseAllowance is disabled pending further community discussion.\");\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    )\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/L2/predeploys/OVM_GasPriceOracle.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 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 is Ownable {\n\n    /*************\n     * Variables *\n     *************/\n\n\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    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _owner Address that will initially own this contract.\n     */\n    constructor(\n        address _owner\n    )\n        Ownable()\n    {\n        transferOwnership(_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\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Allows the owner to modify the l2 gas price.\n     * @param _gasPrice New l2 gas price.\n     */\n    function setGasPrice(\n        uint256 _gasPrice\n    )\n        public\n        onlyOwner\n    {\n        gasPrice = _gasPrice;\n        emit GasPriceUpdated(_gasPrice);\n    }\n\n    /**\n     * Allows the owner to modify the l1 base fee.\n     * @param _baseFee New l1 base fee\n     */\n    function setL1BaseFee(\n        uint256 _baseFee\n    )\n        public\n        onlyOwner\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(\n        uint256 _overhead\n    )\n        public\n        onlyOwner\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(\n        uint256 _scalar\n    )\n        public\n        onlyOwner\n    {\n        scalar = _scalar;\n        emit ScalarUpdated(_scalar);\n    }\n\n    /**\n     * Allows the owner to modify the decimals.\n     * @param _decimals New decimals\n     */\n    function setDecimals(\n        uint256 _decimals\n    )\n        public\n        onlyOwner\n    {\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)\n        public\n        view\n        returns (\n            uint256\n        )\n    {\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    /**\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    function getL1GasUsed(bytes memory _data)\n        public\n        view\n        returns (\n            uint256\n        )\n    {\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"
    },
    "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    /*************\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    /***************\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(\n        address _libAddressManager,\n        string memory _implementationName\n    ) {\n        addressManager[address(this)] = Lib_AddressManager(_libAddressManager);\n        implementationName[address(this)] = _implementationName;\n    }\n\n\n    /*********************\n     * Fallback Function *\n     *********************/\n\n    fallback()\n        external\n        payable\n    {\n        address target = addressManager[address(this)].getAddress(\n            (implementationName[address(this)])\n        );\n\n        require(\n            target != address(0),\n            \"Target address must be initialized.\"\n        );\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"
    },
    "@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"
    },
    "@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"
    },
    "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\";\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\n    // Maps L1 token to L2 token to balance of the L1 token deposited\n    mapping(address => mapping (address => uint256)) public deposits;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    // This contract lives behind a proxy, so the constructor parameters will go unused.\n    constructor()\n        CrossDomainEnabled(address(0))\n    {}\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    )\n        public\n    {\n        require(messenger == address(0), \"Contract has already been initialized.\");\n        messenger = _l1messenger;\n        l2TokenBridge = _l2TokenBridge;\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 This function can be called with no data\n     * to deposit an amount of ETH to the caller's balance on L2.\n     * Since the receive function doesn't take data, a conservative\n     * default amount is forwarded to L2.\n     */\n    receive()\n        external\n        payable\n        onlyEOA()\n    {\n        _initiateETHDeposit(\n            msg.sender,\n            msg.sender,\n            1_300_000,\n            bytes(\"\")\n        );\n    }\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function depositETH(\n        uint32 _l2Gas,\n        bytes calldata _data\n    )\n        external\n        payable\n        onlyEOA()\n    {\n        _initiateETHDeposit(\n            msg.sender,\n            msg.sender,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function depositETHTo(\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    )\n        external\n        payable\n    {\n        _initiateETHDeposit(\n            msg.sender,\n            _to,\n            _l2Gas,\n            _data\n        );\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    )\n        internal\n    {\n        // Construct calldata for finalizeDeposit call\n        bytes memory message =\n            abi.encodeWithSelector(\n                IL2ERC20Bridge.finalizeDeposit.selector,\n                address(0),\n                Lib_PredeployAddresses.OVM_ETH,\n                _from,\n                _to,\n                msg.value,\n                _data\n            );\n\n        // Send calldata into L2\n        sendCrossDomainMessage(\n            l2TokenBridge,\n            _l2Gas,\n            message\n        );\n\n        emit ETHDepositInitiated(_from, _to, msg.value, _data);\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    )\n        external\n        virtual\n        onlyEOA()\n    {\n        _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, msg.sender, _amount, _l2Gas, _data);\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    )\n        external\n        virtual\n    {\n        _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _l2Gas, _data);\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    )\n        internal\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(\n            _from,\n            address(this),\n            _amount\n        );\n\n        // Construct calldata for _l2Token.finalizeDeposit(_to, _amount)\n        bytes memory message = abi.encodeWithSelector(\n            IL2ERC20Bridge.finalizeDeposit.selector,\n            _l1Token,\n            _l2Token,\n            _from,\n            _to,\n            _amount,\n            _data\n        );\n\n        // Send calldata into L2\n        sendCrossDomainMessage(\n            l2TokenBridge,\n            _l2Gas,\n            message\n        );\n\n        deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] + _amount;\n\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    )\n        external\n        onlyFromCrossDomainAccount(l2TokenBridge)\n    {\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);\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    )\n        external\n        onlyFromCrossDomainAccount(l2TokenBridge)\n    {\n        deposits[_l1Token][_l2Token] = deposits[_l1Token][_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 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/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\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    )\n        external\n    {\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/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(\n        address _address\n    )\n        public\n        pure\n        returns (\n            address\n        )\n    {\n        return AddressAliasHelper.applyL1ToL2Alias(_address);\n    }\n\n    function undoL1ToL2Alias(\n        address _address\n    )\n        public\n        pure\n        returns (\n            address\n        )\n    {\n        return AddressAliasHelper.undoL1ToL2Alias(_address);\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\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    )\n        public\n        pure\n        returns (\n            bool\n        )\n    {\n        return Lib_SecureMerkleTrie.verifyInclusionProof(\n            _key,\n            _value,\n            _proof,\n            _root\n        );\n    }\n\n    function update(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    )\n        public\n        pure\n        returns (\n            bytes32\n        )\n    {\n        return Lib_SecureMerkleTrie.update(\n            _key,\n            _value,\n            _proof,\n            _root\n        );\n    }\n\n    function get(\n        bytes memory _key,\n        bytes memory _proof,\n        bytes32 _root\n    )\n        public\n        pure\n        returns (\n            bool,\n            bytes memory\n        )\n    {\n        return Lib_SecureMerkleTrie.get(\n            _key,\n            _proof,\n            _root\n        );\n    }\n\n    function getSingleNodeRootHash(\n        bytes memory _key,\n        bytes memory _value\n    )\n        public\n        pure\n        returns (\n            bytes32\n        )\n    {\n        return Lib_SecureMerkleTrie.getSingleNodeRootHash(\n            _key,\n            _value\n        );\n    }\n}\n"
    },
    "contracts/test-libraries/utils/TestLib_Buffer.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_Buffer } from \"../../libraries/utils/Lib_Buffer.sol\";\n\n/**\n * @title TestLib_Buffer\n */\ncontract TestLib_Buffer {\n    using Lib_Buffer for Lib_Buffer.Buffer;\n\n    Lib_Buffer.Buffer internal buf;\n\n    function push(\n        bytes32 _value,\n        bytes27 _extraData\n    )\n        public\n    {\n        buf.push(\n            _value,\n            _extraData\n        );\n    }\n\n    function get(\n        uint256 _index\n    )\n        public\n        view\n        returns (\n            bytes32\n        )\n    {\n        return buf.get(_index);\n    }\n\n    function deleteElementsAfterInclusive(\n        uint40 _index\n    )\n        public\n    {\n        return buf.deleteElementsAfterInclusive(\n            _index\n        );\n    }\n\n    function deleteElementsAfterInclusive(\n        uint40 _index,\n        bytes27 _extraData\n    )\n        public\n    {\n        return buf.deleteElementsAfterInclusive(\n            _index,\n            _extraData\n        );\n    }\n\n    function getLength()\n        public\n        view\n        returns (\n            uint40\n        )\n    {\n        return buf.getLength();\n    }\n\n    function setExtraData(\n        bytes27 _extraData\n    )\n        public\n    {\n        return buf.setExtraData(\n            _extraData\n        );\n    }\n\n    function getExtraData()\n        public\n        view\n        returns (\n            bytes27\n        )\n    {\n        return buf.getExtraData();\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\n    function getMerkleRoot(\n        bytes32[] memory _elements\n    )\n        public\n       pure\n        returns (\n            bytes32\n        )\n    {\n        return Lib_MerkleTree.getMerkleRoot(\n            _elements\n        );\n    }\n\n    function verify(\n        bytes32 _root,\n        bytes32 _leaf,\n        uint256 _index,\n        bytes32[] memory _siblings,\n        uint256 _totalLeaves\n    )\n        public\n        pure\n        returns (\n            bool\n        )\n    {\n        return Lib_MerkleTree.verify(\n            _root,\n            _leaf,\n            _index,\n            _siblings,\n            _totalLeaves\n        );\n    }\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 10000
    },
    "metadata": {
      "bytecodeHash": "none",
      "useLiteralContent": true
    },
    "outputSelection": {
      "*": {
        "*": [
          "storageLayout",
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    }
  }
}