creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@ensdomains/evm-verifier/contracts/EVMFetcher.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { IEVMVerifier } from './IEVMVerifier.sol';\nimport { EVMFetchTarget } from './EVMFetchTarget.sol';\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\n\ninterface IEVMGateway {\n    function getStorageSlots(address addr, bytes32[] memory commands, bytes[] memory constants) external pure returns(bytes memory witness);\n}\n\nuint8 constant FLAG_DYNAMIC = 0x01;\nuint8 constant OP_CONSTANT = 0x00;\nuint8 constant OP_BACKREF = 0x20;\nuint8 constant OP_END = 0xff;\n\n/**\n * @dev A library to facilitate requesting storage data proofs from contracts, possibly on a different chain.\n *      See l1-verifier/test/TestL1.sol for example usage.\n */\nlibrary EVMFetcher {\n    uint256 constant MAX_COMMANDS = 32;\n    uint256 constant MAX_CONSTANTS = 32; // Must not be greater than 32\n\n    using Address for address;\n\n    error TooManyCommands(uint256 max);\n    error CommandTooLong();\n    error InvalidReference(uint256 value, uint256 max);\n    error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData);\n\n    struct EVMFetchRequest {\n        IEVMVerifier verifier;\n        address target;\n        bytes32[] commands;\n        uint256 operationIdx;\n        bytes[] constants;\n    }\n\n    /**\n     * @dev Creates a request to fetch the value of multiple storage slots from a contract via CCIP-Read, possibly from\n     *      another chain.\n     *      Supports dynamic length values and slot numbers derived from other retrieved values.\n     * @param verifier An instance of a verifier contract that can provide and verify the storage slot information.\n     * @param target The address of the contract to fetch storage proofs for.\n     */\n    function newFetchRequest(IEVMVerifier verifier, address target) internal pure returns (EVMFetchRequest memory) {\n        bytes32[] memory commands = new bytes32[](MAX_COMMANDS);\n        bytes[] memory constants = new bytes[](MAX_CONSTANTS);\n        assembly {\n            mstore(commands, 0) // Set current array length to 0\n            mstore(constants, 0)\n        }        \n        return EVMFetchRequest(verifier, target, commands, 0, constants);\n    }\n\n    /**\n     * @dev Starts describing a new fetch request.\n     *      Paths specify a series of hashing operations to derive the final slot ID.\n     *      See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\n     *      lays out storage variables.\n     * @param request The request object being operated on.\n     * @param baseSlot The base slot ID that forms the root of the path.\n     */\n    function getStatic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\n        bytes32[] memory commands = request.commands;\n        uint256 commandIdx = commands.length;\n        if(commandIdx > 0 && request.operationIdx < 32) {\n            // Terminate previous command\n            _addOperation(request, OP_END);\n        }\n        assembly {\n            mstore(commands, add(commandIdx, 1)) // Increment command array length\n        }\n        if(request.commands.length > MAX_COMMANDS) {\n            revert TooManyCommands(MAX_COMMANDS);\n        }\n        request.operationIdx = 0;\n        _addOperation(request, 0);\n        _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\n        return request;\n    }\n\n    /**\n     * @dev Starts describing a new fetch request.\n     *      Paths specify a series of hashing operations to derive the final slot ID.\n     *      See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\n     *      lays out storage variables.\n     * @param request The request object being operated on.\n     * @param baseSlot The base slot ID that forms the root of the path.\n     */\n    function getDynamic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\n        bytes32[] memory commands = request.commands;\n        uint256 commandIdx = commands.length;\n        if(commandIdx > 0 && request.operationIdx < 32) {\n            // Terminate previous command\n            _addOperation(request, OP_END);\n        }\n        assembly {\n            mstore(commands, add(commandIdx, 1)) // Increment command array length\n        }\n        if(request.commands.length > MAX_COMMANDS) {\n            revert TooManyCommands(MAX_COMMANDS);\n        }\n        request.operationIdx = 0;\n        _addOperation(request, FLAG_DYNAMIC);\n        _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\n        return request;\n    }\n\n    /**\n     * @dev Adds a `uint256` element to the current path.\n     * @param request The request object being operated on.\n     * @param el The element to add.\n     */\n    function element(EVMFetchRequest memory request, uint256 el) internal pure returns (EVMFetchRequest memory) {\n        if(request.operationIdx >= 32) {\n            revert CommandTooLong();\n        }\n        _addOperation(request, _addConstant(request, abi.encode(el)));\n        return request;\n    }\n\n    /**\n     * @dev Adds a `bytes32` element to the current path.\n     * @param request The request object being operated on.\n     * @param el The element to add.\n     */\n    function element(EVMFetchRequest memory request, bytes32 el) internal pure returns (EVMFetchRequest memory) {\n        if(request.operationIdx >= 32) {\n            revert CommandTooLong();\n        }\n        _addOperation(request, _addConstant(request, abi.encode(el)));\n        return request;\n    }\n\n    /**\n     * @dev Adds an `address` element to the current path.\n     * @param request The request object being operated on.\n     * @param el The element to add.\n     */\n    function element(EVMFetchRequest memory request, address el) internal pure returns (EVMFetchRequest memory) {\n        if(request.operationIdx >= 32) {\n            revert CommandTooLong();\n        }\n        _addOperation(request, _addConstant(request, abi.encode(el)));\n        return request;\n    }\n\n    /**\n     * @dev Adds a `bytes` element to the current path.\n     * @param request The request object being operated on.\n     * @param el The element to add.\n     */\n    function element(EVMFetchRequest memory request, bytes memory el) internal pure returns (EVMFetchRequest memory) {\n        if(request.operationIdx >= 32) {\n            revert CommandTooLong();\n        }\n        _addOperation(request, _addConstant(request, el));\n        return request;\n    }\n\n    /**\n     * @dev Adds a `string` element to the current path.\n     * @param request The request object being operated on.\n     * @param el The element to add.\n     */\n    function element(EVMFetchRequest memory request, string memory el) internal pure returns (EVMFetchRequest memory) {\n        if(request.operationIdx >= 32) {\n            revert CommandTooLong();\n        }\n        _addOperation(request, _addConstant(request, bytes(el)));\n        return request;\n    }\n\n    /**\n     * @dev Adds a reference to a previous fetch to the current path.\n     * @param request The request object being operated on.\n     * @param idx The index of the previous fetch request, starting at 0.\n     */\n    function ref(EVMFetchRequest memory request, uint8 idx) internal pure returns (EVMFetchRequest memory) {\n        if(request.operationIdx >= 32) {\n            revert CommandTooLong();\n        }\n        if(idx > request.commands.length || idx > 31) {\n            revert InvalidReference(idx, request.commands.length);\n        }\n        _addOperation(request, OP_BACKREF | idx);\n        return request;\n    }\n\n    /**\n     * @dev Initiates the fetch request.\n     *      Calling this function terminates execution; clients that implement CCIP-Read will make a callback to\n     *      `callback` with the results of the operation.\n     * @param callbackId A callback function selector on this contract that will be invoked via CCIP-Read with the result of the lookup.\n     *        The function must have a signature matching `(bytes[] memory values, bytes callbackData)` with a return type matching the call in which\n     *        this function was invoked. Its return data will be returned as the return value of the entire CCIP-read operation.\n     * @param callbackData Extra data to supply to the callback.\n     */\n    function fetch(EVMFetchRequest memory request, bytes4 callbackId, bytes memory callbackData) internal view {\n        if(request.commands.length > 0 && request.operationIdx < 32) {\n            // Terminate last command\n            _addOperation(request, OP_END);\n        }\n        revert OffchainLookup(\n            address(this),\n            request.verifier.gatewayURLs(),\n            abi.encodeCall(IEVMGateway.getStorageSlots, (request.target, request.commands, request.constants)),\n            EVMFetchTarget.getStorageSlotsCallback.selector,\n            abi.encode(request.verifier, request.target, request.commands, request.constants, callbackId, callbackData)\n        );\n    }\n\n    function _addConstant(EVMFetchRequest memory request, bytes memory value) private pure returns(uint8 idx) {\n        bytes[] memory constants = request.constants;\n        idx = uint8(constants.length);\n        assembly {\n            mstore(constants, add(idx, 1)) // Increment constant array length\n        }\n        constants[idx] = value;\n    }\n\n    function _addOperation(EVMFetchRequest memory request, uint8 op) private pure {\n        uint256 commandIdx = request.commands.length - 1;\n        request.commands[commandIdx] = request.commands[commandIdx] | (bytes32(bytes1(op)) >> (8 * request.operationIdx++));\n    }\n}\n"
      },
      "@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { IEVMVerifier } from './IEVMVerifier.sol';\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\n\n/**\n * @dev Callback implementation for users of `EVMFetcher`. If you use `EVMFetcher`, your contract must\n *      inherit from this contract in order to handle callbacks correctly.\n */\nabstract contract EVMFetchTarget {\n    using Address for address;\n\n    error ResponseLengthMismatch(uint256 actual, uint256 expected);\n\n    /**\n     * @dev Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\n     */\n    function getStorageSlotsCallback(bytes calldata response, bytes calldata extradata) external {\n        bytes memory proof = abi.decode(response, (bytes));\n        (IEVMVerifier verifier, address addr, bytes32[] memory commands, bytes[] memory constants, bytes4 callback, bytes memory callbackData) =\n            abi.decode(extradata, (IEVMVerifier, address, bytes32[], bytes[], bytes4, bytes));\n        bytes[] memory values = verifier.getStorageValues(addr, commands, constants, proof);\n        if(values.length != commands.length) {\n            revert ResponseLengthMismatch(values.length, commands.length);\n        }\n        bytes memory ret = address(this).functionCall(abi.encodeWithSelector(callback, values, callbackData));\n        assembly {\n            return(add(ret, 32), mload(ret))\n        }\n    }\n}\n"
      },
      "@ensdomains/evm-verifier/contracts/EVMProofHelper.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport {RLPReader} from \"@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol\";\nimport {Bytes} from \"@eth-optimism/contracts-bedrock/src/libraries/Bytes.sol\";\nimport {SecureMerkleTrie} from \"./SecureMerkleTrie.sol\";\n\nstruct StateProof {\n    bytes[] stateTrieWitness;         // Witness proving the `storageRoot` against a state root.\n    bytes[][] storageProofs;          // An array of proofs of individual storage elements \n}\n\nuint8 constant OP_CONSTANT = 0x00;\nuint8 constant OP_BACKREF = 0x20;\nuint8 constant FLAG_DYNAMIC = 0x01;\n\nlibrary EVMProofHelper {\n    using Bytes for bytes;\n\n    error AccountNotFound(address);\n    error UnknownOpcode(uint8);\n    error InvalidSlotSize(uint256 size);\n\n    /**\n     * @notice Get the storage root for the provided merkle proof\n     * @param stateRoot The state root the witness was generated against\n     * @param target The address we are fetching a storage root for\n     * @param witness A witness proving the value of the storage root for `target`.\n     * @return The storage root retrieved from the provided state root\n     */\n    function getStorageRoot(bytes32 stateRoot, address target, bytes[] memory witness) private pure returns (bytes32) {\n        (bool exists, bytes memory encodedResolverAccount) = SecureMerkleTrie.get(\n            abi.encodePacked(target),\n            witness,\n            stateRoot\n        );\n        if(!exists) {\n            revert AccountNotFound(target);\n        }\n        RLPReader.RLPItem[] memory accountState = RLPReader.readList(encodedResolverAccount);\n        return bytes32(RLPReader.readBytes(accountState[2]));\n    }\n\n    /**\n     * @notice Prove whether the provided storage slot is part of the storageRoot\n     * @param storageRoot the storage root for the account that contains the storage slot\n     * @param slot The storage key we are fetching the value of\n     * @param witness the StorageProof struct containing the necessary proof data\n     * @return The retrieved storage proof value or 0x if the storage slot is empty\n     */\n    function getSingleStorageProof(bytes32 storageRoot, uint256 slot, bytes[] memory witness) private pure returns (bytes memory) {\n        (bool exists, bytes memory retrievedValue) = SecureMerkleTrie.get(\n            abi.encodePacked(slot),\n            witness,\n            storageRoot\n        );\n        if(!exists) {\n            // Nonexistent values are treated as zero.\n            return \"\";\n        }\n        return RLPReader.readBytes(retrievedValue);\n    }\n\n    function getFixedValue(bytes32 storageRoot, uint256 slot, bytes[] memory witness) private pure returns(bytes32) {\n        bytes memory value = getSingleStorageProof(storageRoot, slot, witness);\n        // RLP encoded storage slots are stored without leading 0 bytes.\n        // Casting to bytes32 appends trailing 0 bytes, so we have to bit shift to get the \n        // original fixed-length representation back.\n        return bytes32(value) >> (256 - 8 * value.length);\n    }\n\n    function executeOperation(bytes1 operation, bytes[] memory constants, bytes[] memory values) private pure returns(bytes memory) {\n        uint8 opcode = uint8(operation) & 0xe0;\n        uint8 operand = uint8(operation) & 0x1f;\n\n        if(opcode == OP_CONSTANT) {\n            return constants[operand];\n        } else if(opcode == OP_BACKREF) {\n            return values[operand];\n        } else {\n            revert UnknownOpcode(opcode);\n        }\n    }\n\n    function computeFirstSlot(bytes32 command, bytes[] memory constants, bytes[] memory values) private pure returns(bool isDynamic, uint256 slot) {\n        uint8 flags = uint8(command[0]);\n        isDynamic = (flags & FLAG_DYNAMIC) != 0;\n\n        bytes memory slotData = executeOperation(command[1], constants, values);\n        require(slotData.length == 32, \"First path element must be 32 bytes\");\n        slot = uint256(bytes32(slotData));\n\n        for(uint256 j = 2; j < 32 && command[j] != 0xff; j++) {\n            bytes memory index = executeOperation(command[j], constants, values);\n            slot = uint256(keccak256(abi.encodePacked(index, slot)));\n        }\n    }\n\n    function getDynamicValue(bytes32 storageRoot, uint256 slot, StateProof memory proof, uint256 proofIdx) private pure returns(bytes memory value, uint256 newProofIdx) {\n        uint256 firstValue = uint256(getFixedValue(storageRoot, slot, proof.storageProofs[proofIdx++]));\n        if(firstValue & 0x01 == 0x01) {\n            // Long value: first slot is `length * 2 + 1`, following slots are data.\n            uint256 length = (firstValue - 1) / 2;\n            value = \"\";\n            slot = uint256(keccak256(abi.encodePacked(slot)));\n            // This is horribly inefficient - O(n^2). A better approach would be to build an array of words and concatenate them\n            // all at once, but we're trying to avoid writing new library code.\n            while(length > 0) {\n                if(length < 32) {\n                    value = bytes.concat(value, getSingleStorageProof(storageRoot, slot++, proof.storageProofs[proofIdx++]).slice(0, length));\n                    length = 0;\n                } else {\n                    value = bytes.concat(value, getSingleStorageProof(storageRoot, slot++, proof.storageProofs[proofIdx++]));\n                    length -= 32;\n                }\n            }\n            return (value, proofIdx);\n        } else {\n            // Short value: least significant byte is `length * 2`, other bytes are data.\n            uint256 length = (firstValue & 0xFF) / 2;\n            return (abi.encode(firstValue).slice(0, length), proofIdx);\n        }\n    }\n\n    function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes32 stateRoot, StateProof memory proof) internal pure returns(bytes[] memory values) {\n        bytes32 storageRoot = getStorageRoot(stateRoot, target, proof.stateTrieWitness);\n        uint256 proofIdx = 0;\n        values = new bytes[](commands.length);\n        for(uint256 i = 0; i < commands.length; i++) {\n            bytes32 command = commands[i];\n            (bool isDynamic, uint256 slot) = computeFirstSlot(command, constants, values);\n            if(!isDynamic) {\n                values[i] = abi.encode(getFixedValue(storageRoot, slot, proof.storageProofs[proofIdx++]));\n                if(values[i].length > 32) {\n                    revert InvalidSlotSize(values[i].length);\n                }\n            } else {\n                (values[i], proofIdx) = getDynamicValue(storageRoot, slot, proof, proofIdx);\n            }\n        }\n    }\n}"
      },
      "@ensdomains/evm-verifier/contracts/IEVMVerifier.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\ninterface IEVMVerifier {\n    function gatewayURLs() external view returns(string[] memory);\n    function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values);\n}\n"
      },
      "@ensdomains/evm-verifier/contracts/MerkleTrie.sol": {
        "content": "// Pulled from https://github.com/ethereum-optimism/optimism/blob/4d13f0afe8869faf7bba45d8339998525ebc5161/packages/contracts-bedrock/contracts/libraries/trie/MerkleTrie.sol\n//   as this is the last version of Optimism's Merkle Trie library that supports nonexistence proofs; support was removed\n//   in the next commit for some version.\n// Copyright 2020-2021 Optimism\n// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { Bytes } from \"@eth-optimism/contracts-bedrock/src/libraries/Bytes.sol\";\nimport { RLPReader } from \"@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol\";\n\n\n/**\n * @title MerkleTrie\n * @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie\n *         inclusion proofs. By default, this library assumes a hexary trie. One can change the\n *         trie radix constant to support other trie radixes.\n */\nlibrary MerkleTrie {\n    /**\n     * @notice Struct representing a node in the trie.\n     */\n    struct TrieNode {\n        bytes encoded;\n        RLPReader.RLPItem[] decoded;\n    }\n\n    /**\n     * @notice Determines the number of elements per branch node.\n     */\n    uint256 internal constant TREE_RADIX = 16;\n\n    /**\n     * @notice Branch nodes have TREE_RADIX elements and one value element.\n     */\n    uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n\n    /**\n     * @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.\n     */\n    uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n    /**\n     * @notice Prefix for even-nibbled extension node paths.\n     */\n    uint8 internal constant PREFIX_EXTENSION_EVEN = 0;\n\n    /**\n     * @notice Prefix for odd-nibbled extension node paths.\n     */\n    uint8 internal constant PREFIX_EXTENSION_ODD = 1;\n\n    /**\n     * @notice Prefix for even-nibbled leaf node paths.\n     */\n    uint8 internal constant PREFIX_LEAF_EVEN = 2;\n\n    /**\n     * @notice Prefix for odd-nibbled leaf node paths.\n     */\n    uint8 internal constant PREFIX_LEAF_ODD = 3;\n\n    /**\n     * @notice RLP representation of `NULL`.\n     */\n    bytes internal constant RLP_NULL = hex\"80\";\n\n    /**\n     * @notice Verifies a proof that a given key/value pair is present in the trie.\n     *\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 traditional Merkle\n     *               trees, this proof is executed top-down and consists of a list of RLP-encoded\n     *               nodes that make a path down to the target node.\n     * @param _root  Known root of the Merkle trie. Used to verify that the included proof is\n     *               correctly constructed.\n     *\n     * @return Whether or not the proof is valid.\n     */\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes[] memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool) {\n        (bool exists, bytes memory value) = get(_key, _proof, _root);\n        return (exists && Bytes.equal(_value, value));\n    }\n\n    /**\n     * @notice Retrieves the value associated with a given key.\n     *\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     *\n     * @return Whether or not the key exists.\n     * @return Value of the key if it exists.\n     */\n    function get(\n        bytes memory _key,\n        bytes[] memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool, bytes memory) {\n        TrieNode[] memory proof = _parseProof(_proof);\n        (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(\n            proof,\n            _key,\n            _root\n        );\n\n        bool noRemainder = keyRemainder.length == 0;\n\n        require(noRemainder || isFinalNode, \"MerkleTrie: provided proof is invalid\");\n\n        bytes memory value = noRemainder ? _getNodeValue(proof[pathLength - 1]) : bytes(\"\");\n\n        return (value.length > 0, value);\n    }\n\n    /**\n     * @notice Walks through a proof using a provided key.\n     *\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     *\n     * @return Length of the final path\n     * @return Portion of the key remaining after the walk.\n     * @return Whether or not we've hit a dead end.\n     */\n    // solhint-disable-next-line code-complexity\n    function _walkNodePath(\n        TrieNode[] memory _proof,\n        bytes memory _key,\n        bytes32 _root\n    )\n        private\n        pure\n        returns (\n            uint256,\n            bytes memory,\n            bool\n        )\n    {\n        uint256 pathLength = 0;\n        bytes memory key = Bytes.toNibbles(_key);\n\n        bytes memory currentNodeID = abi.encodePacked(_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                    Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n                    \"MerkleTrie: 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                    Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n                    \"MerkleTrie: invalid large internal hash\"\n                );\n            } else {\n                // Nodes smaller than 32 bytes aren't hashed.\n                require(\n                    Bytes.equal(currentNode.encoded, currentNodeID),\n                    \"MerkleTrie: 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                    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 = Bytes.slice(path, offset);\n                bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);\n                uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n                require(\n                    keyRemainder.length >= pathRemainder.length,\n                    \"MerkleTrie: invalid key length for leaf or extension node\"\n                );\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 = 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 = 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(\"MerkleTrie: received a node with an unknown prefix\");\n                }\n            } else {\n                revert(\"MerkleTrie: received an unparseable node\");\n            }\n        }\n\n        return (\n            pathLength,\n            Bytes.slice(key, currentKeyIndex),\n            Bytes.equal(currentNodeID, RLP_NULL)\n        );\n    }\n\n    /**\n     * @notice Parses an array of proof elements into a new array that contains both the original\n     *         encoded element and the RLP-decoded element.\n     *\n     * @param _proof Array of proof elements to parse.\n     *\n     * @return Proof parsed into easily accessible structs.\n     */\n    function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory) {\n        uint256 length = _proof.length;\n        TrieNode[] memory proof = new TrieNode[](length);\n        for (uint256 i = 0; i < length; ) {\n            proof[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });\n            unchecked {\n                ++i;\n            }\n        }\n        return proof;\n    }\n\n    /**\n     * @notice Picks out the ID for a node. Node ID is referred to as the \"hash\" within the\n     *         specification, but nodes < 32 bytes are not actually hashed.\n     *\n     * @param _node Node to pull an ID for.\n     *\n     * @return ID for the node, depending on the size of its contents.\n     */\n    function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory) {\n        return _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);\n    }\n\n    /**\n     * @notice Gets the path for a leaf or extension node.\n     *\n     * @param _node Node to get a path for.\n     *\n     * @return Node path, converted to an array of nibbles.\n     */\n    function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {\n        return Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));\n    }\n\n    /**\n     * @notice Gets the value for a node.\n     *\n     * @param _node Node to get a value for.\n     *\n     * @return Node value, as hex bytes.\n     */\n    function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory) {\n        return RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]);\n    }\n\n    /**\n     * @notice Utility; determines the number of nibbles shared between two nibble arrays.\n     *\n     * @param _a First nibble array.\n     * @param _b Second nibble array.\n     *\n     * @return Number of shared nibbles.\n     */\n    function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n        private\n        pure\n        returns (uint256)\n    {\n        uint256 shared;\n        uint256 max = (_a.length < _b.length) ? _a.length : _b.length;\n        for (; shared < max && _a[shared] == _b[shared]; ) {\n            unchecked {\n                ++shared;\n            }\n        }\n        return shared;\n    }\n}"
      },
      "@ensdomains/evm-verifier/contracts/SecureMerkleTrie.sol": {
        "content": "// Pulled from https://github.com/ethereum-optimism/optimism/blob/4d13f0afe8869faf7bba45d8339998525ebc5161/packages/contracts-bedrock/contracts/libraries/trie/MerkleTrie.sol\n//   as this is the last version of Optimism's Merkle Trie library that supports nonexistence proofs; support was removed\n//   in the next commit for some version.\n// Copyright 2020-2021 Optimism\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Library Imports */\nimport { MerkleTrie } from \"./MerkleTrie.sol\";\n\n/**\n * @title SecureMerkleTrie\n * @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input\n *         keys. Ethereum's state trie hashes input keys before storing them.\n */\nlibrary SecureMerkleTrie {\n    /**\n     * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.\n     *\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 traditional Merkle\n     *               trees, this proof is executed top-down and consists of a list of RLP-encoded\n     *               nodes that make a path down to the target node.\n     * @param _root  Known root of the Merkle trie. Used to verify that the included proof is\n     *               correctly constructed.\n     *\n     * @return Whether or not the proof is valid.\n     */\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes[] memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool) {\n        bytes memory key = _getSecureKey(_key);\n        return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n    }\n\n    /**\n     * @notice Retrieves the value associated with a given key.\n     *\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     *\n     * @return Whether or not the key exists.\n     * @return Value of the key if it exists.\n     */\n    function get(\n        bytes memory _key,\n        bytes[] memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool, bytes memory) {\n        bytes memory key = _getSecureKey(_key);\n        return MerkleTrie.get(key, _proof, _root);\n    }\n\n    /**\n     * @notice Computes the hashed version of the input key.\n     *\n     * @param _key Key to hash.\n     *\n     * @return Hashed version of the key.\n     */\n    function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {\n        return abi.encodePacked(keccak256(_key));\n    }\n}"
      },
      "@eth-optimism/contracts-bedrock/src/libraries/Bytes.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Bytes\n/// @notice Bytes is a library for manipulating byte arrays.\nlibrary Bytes {\n    /// @custom:attribution https://github.com/GNSPS/solidity-bytes-utils\n    /// @notice Slices a byte array with a given starting index and length. Returns a new byte array\n    ///         as opposed to a pointer to the original array. Will throw if trying to slice more\n    ///         bytes than exist in the array.\n    /// @param _bytes Byte array to slice.\n    /// @param _start Starting index of the slice.\n    /// @param _length Length of the slice.\n    /// @return Slice of the input byte array.\n    function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {\n        unchecked {\n            require(_length + 31 >= _length, \"slice_overflow\");\n            require(_start + _length >= _start, \"slice_overflow\");\n            require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n        }\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                } { mstore(mc, mload(cc)) }\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    /// @notice Slices a byte array with a given starting index up to the end of the original byte\n    ///         array. Returns a new array rathern than a pointer to the original.\n    /// @param _bytes Byte array to slice.\n    /// @param _start Starting index of the slice.\n    /// @return Slice of the input byte array.\n    function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n        if (_start >= _bytes.length) {\n            return bytes(\"\");\n        }\n        return slice(_bytes, _start, _bytes.length - _start);\n    }\n\n    /// @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.\n    ///         Resulting nibble array will be exactly twice as long as the input byte array.\n    /// @param _bytes Input byte array to convert.\n    /// @return Resulting nibble array.\n    function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n        bytes memory _nibbles;\n        assembly {\n            // Grab a free memory offset for the new array\n            _nibbles := mload(0x40)\n\n            // Load the length of the passed bytes array from memory\n            let bytesLength := mload(_bytes)\n\n            // Calculate the length of the new nibble array\n            // This is the length of the input array times 2\n            let nibblesLength := shl(0x01, bytesLength)\n\n            // Update the free memory pointer to allocate memory for the new array.\n            // To do this, we add the length of the new array + 32 bytes for the array length\n            // rounded up to the nearest 32 byte boundary to the current free memory pointer.\n            mstore(0x40, add(_nibbles, and(not(0x1F), add(nibblesLength, 0x3F))))\n\n            // Store the length of the new array in memory\n            mstore(_nibbles, nibblesLength)\n\n            // Store the memory offset of the _bytes array's contents on the stack\n            let bytesStart := add(_bytes, 0x20)\n\n            // Store the memory offset of the nibbles array's contents on the stack\n            let nibblesStart := add(_nibbles, 0x20)\n\n            // Loop through each byte in the input array\n            for { let i := 0x00 } lt(i, bytesLength) { i := add(i, 0x01) } {\n                // Get the starting offset of the next 2 bytes in the nibbles array\n                let offset := add(nibblesStart, shl(0x01, i))\n                // Load the byte at the current index within the `_bytes` array\n                let b := byte(0x00, mload(add(bytesStart, i)))\n\n                // Pull out the first nibble and store it in the new array\n                mstore8(offset, shr(0x04, b))\n                // Pull out the second nibble and store it in the new array\n                mstore8(add(offset, 0x01), and(b, 0x0F))\n            }\n        }\n        return _nibbles;\n    }\n\n    /// @notice Compares two byte arrays by comparing their keccak256 hashes.\n    /// @param _bytes First byte array to compare.\n    /// @param _other Second byte array to compare.\n    /// @return True if the two byte arrays are equal, false otherwise.\n    function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n        return keccak256(_bytes) == keccak256(_other);\n    }\n}\n"
      },
      "@eth-optimism/contracts-bedrock/src/libraries/Encoding.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Hashing } from \"./Hashing.sol\";\nimport { RLPWriter } from \"./rlp/RLPWriter.sol\";\n\n/// @title Encoding\n/// @notice Encoding handles Optimism's various different encoding schemes.\nlibrary Encoding {\n    /// @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\n    ///         to the L2 system. Useful for searching for a deposit in the L2 system. The\n    ///         transaction is prefixed with 0x7e to identify its EIP-2718 type.\n    /// @param _tx User deposit transaction to encode.\n    /// @return RLP encoded L2 deposit transaction.\n    function encodeDepositTransaction(Types.UserDepositTransaction memory _tx) internal pure returns (bytes memory) {\n        bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\n        bytes[] memory raw = new bytes[](8);\n        raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\n        raw[1] = RLPWriter.writeAddress(_tx.from);\n        raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\"\") : RLPWriter.writeAddress(_tx.to);\n        raw[3] = RLPWriter.writeUint(_tx.mint);\n        raw[4] = RLPWriter.writeUint(_tx.value);\n        raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\n        raw[6] = RLPWriter.writeBool(false);\n        raw[7] = RLPWriter.writeBytes(_tx.data);\n        return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\n    }\n\n    /// @notice Encodes the cross domain message based on the version that is encoded into the\n    ///         message nonce.\n    /// @param _nonce    Message nonce with version encoded into the first two bytes.\n    /// @param _sender   Address of the sender of the message.\n    /// @param _target   Address of the target of the message.\n    /// @param _value    ETH value to send to the target.\n    /// @param _gasLimit Gas limit to use for the message.\n    /// @param _data     Data to send with the message.\n    /// @return Encoded cross domain message.\n    function encodeCrossDomainMessage(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    )\n        internal\n        pure\n        returns (bytes memory)\n    {\n        (, uint16 version) = decodeVersionedNonce(_nonce);\n        if (version == 0) {\n            return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\n        } else if (version == 1) {\n            return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n        } else {\n            revert(\"Encoding: unknown cross domain message version\");\n        }\n    }\n\n    /// @notice Encodes a cross domain message based on the V0 (legacy) encoding.\n    /// @param _target Address of the target of the message.\n    /// @param _sender Address of the sender of the message.\n    /// @param _data   Data to send with the message.\n    /// @param _nonce  Message nonce.\n    /// @return Encoded cross domain message.\n    function encodeCrossDomainMessageV0(\n        address _target,\n        address _sender,\n        bytes memory _data,\n        uint256 _nonce\n    )\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodeWithSignature(\"relayMessage(address,address,bytes,uint256)\", _target, _sender, _data, _nonce);\n    }\n\n    /// @notice Encodes a cross domain message based on the V1 (current) encoding.\n    /// @param _nonce    Message nonce.\n    /// @param _sender   Address of the sender of the message.\n    /// @param _target   Address of the target of the message.\n    /// @param _value    ETH value to send to the target.\n    /// @param _gasLimit Gas limit to use for the message.\n    /// @param _data     Data to send with the message.\n    /// @return Encoded cross domain message.\n    function encodeCrossDomainMessageV1(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    )\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodeWithSignature(\n            \"relayMessage(uint256,address,address,uint256,uint256,bytes)\",\n            _nonce,\n            _sender,\n            _target,\n            _value,\n            _gasLimit,\n            _data\n        );\n    }\n\n    /// @notice Adds a version number into the first two bytes of a message nonce.\n    /// @param _nonce   Message nonce to encode into.\n    /// @param _version Version number to encode into the message nonce.\n    /// @return Message nonce with version encoded into the first two bytes.\n    function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\n        uint256 nonce;\n        assembly {\n            nonce := or(shl(240, _version), _nonce)\n        }\n        return nonce;\n    }\n\n    /// @notice Pulls the version out of a version-encoded nonce.\n    /// @param _nonce Message nonce with version encoded into the first two bytes.\n    /// @return Nonce without encoded version.\n    /// @return Version of the message.\n    function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\n        uint240 nonce;\n        uint16 version;\n        assembly {\n            nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\n            version := shr(240, _nonce)\n        }\n        return (nonce, version);\n    }\n}\n"
      },
      "@eth-optimism/contracts-bedrock/src/libraries/Hashing.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Encoding } from \"./Encoding.sol\";\n\n/// @title Hashing\n/// @notice Hashing handles Optimism's various different hashing schemes.\nlibrary Hashing {\n    /// @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\n    ///         given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\n    ///         system.\n    /// @param _tx User deposit transaction to hash.\n    /// @return Hash of the RLP encoded L2 deposit transaction.\n    function hashDepositTransaction(Types.UserDepositTransaction memory _tx) internal pure returns (bytes32) {\n        return keccak256(Encoding.encodeDepositTransaction(_tx));\n    }\n\n    /// @notice Computes the deposit transaction's \"source hash\", a value that guarantees the hash\n    ///         of the L2 transaction that corresponds to a deposit is unique and is\n    ///         deterministically generated from L1 transaction data.\n    /// @param _l1BlockHash Hash of the L1 block where the deposit was included.\n    /// @param _logIndex    The index of the log that created the deposit transaction.\n    /// @return Hash of the deposit transaction's \"source hash\".\n    function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex) internal pure returns (bytes32) {\n        bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\n        return keccak256(abi.encode(bytes32(0), depositId));\n    }\n\n    /// @notice Hashes the cross domain message based on the version that is encoded into the\n    ///         message nonce.\n    /// @param _nonce    Message nonce with version encoded into the first two bytes.\n    /// @param _sender   Address of the sender of the message.\n    /// @param _target   Address of the target of the message.\n    /// @param _value    ETH value to send to the target.\n    /// @param _gasLimit Gas limit to use for the message.\n    /// @param _data     Data to send with the message.\n    /// @return Hashed cross domain message.\n    function hashCrossDomainMessage(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    )\n        internal\n        pure\n        returns (bytes32)\n    {\n        (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n        if (version == 0) {\n            return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\n        } else if (version == 1) {\n            return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n        } else {\n            revert(\"Hashing: unknown cross domain message version\");\n        }\n    }\n\n    /// @notice Hashes a cross domain message based on the V0 (legacy) encoding.\n    /// @param _target Address of the target of the message.\n    /// @param _sender Address of the sender of the message.\n    /// @param _data   Data to send with the message.\n    /// @param _nonce  Message nonce.\n    /// @return Hashed cross domain message.\n    function hashCrossDomainMessageV0(\n        address _target,\n        address _sender,\n        bytes memory _data,\n        uint256 _nonce\n    )\n        internal\n        pure\n        returns (bytes32)\n    {\n        return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\n    }\n\n    /// @notice Hashes a cross domain message based on the V1 (current) encoding.\n    /// @param _nonce    Message nonce.\n    /// @param _sender   Address of the sender of the message.\n    /// @param _target   Address of the target of the message.\n    /// @param _value    ETH value to send to the target.\n    /// @param _gasLimit Gas limit to use for the message.\n    /// @param _data     Data to send with the message.\n    /// @return Hashed cross domain message.\n    function hashCrossDomainMessageV1(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    )\n        internal\n        pure\n        returns (bytes32)\n    {\n        return keccak256(Encoding.encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data));\n    }\n\n    /// @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\n    /// @param _tx Withdrawal transaction to hash.\n    /// @return Hashed withdrawal transaction.\n    function hashWithdrawal(Types.WithdrawalTransaction memory _tx) internal pure returns (bytes32) {\n        return keccak256(abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data));\n    }\n\n    /// @notice Hashes the various elements of an output root proof into an output root hash which\n    ///         can be used to check if the proof is valid.\n    /// @param _outputRootProof Output root proof which should hash to an output root.\n    /// @return Hashed output root proof.\n    function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof) internal pure returns (bytes32) {\n        return keccak256(\n            abi.encode(\n                _outputRootProof.version,\n                _outputRootProof.stateRoot,\n                _outputRootProof.messagePasserStorageRoot,\n                _outputRootProof.latestBlockhash\n            )\n        );\n    }\n}\n"
      },
      "@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/// @custom:attribution https://github.com/hamdiallam/Solidity-RLP\n/// @title RLPReader\n/// @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted\n///         from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with\n///         various tweaks to improve readability.\nlibrary RLPReader {\n    /// @notice Custom pointer type to avoid confusion between pointers and uint256s.\n    type MemoryPointer is uint256;\n\n    /// @notice RLP item types.\n    /// @custom:value DATA_ITEM Represents an RLP data item (NOT a list).\n    /// @custom:value LIST_ITEM Represents an RLP list item.\n    enum RLPItemType {\n        DATA_ITEM,\n        LIST_ITEM\n    }\n\n    /// @notice Struct representing an RLP item.\n    /// @custom:field length Length of the RLP item.\n    /// @custom:field ptr    Pointer to the RLP item in memory.\n    struct RLPItem {\n        uint256 length;\n        MemoryPointer ptr;\n    }\n\n    /// @notice Max list length that this library will accept.\n    uint256 internal constant MAX_LIST_LENGTH = 32;\n\n    /// @notice Converts bytes to a reference to memory position and length.\n    /// @param _in Input bytes to convert.\n    /// @return out_ Output memory reference.\n    function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory out_) {\n        // Empty arrays are not RLP items.\n        require(_in.length > 0, \"RLPReader: length of an RLP item must be greater than zero to be decodable\");\n\n        MemoryPointer ptr;\n        assembly {\n            ptr := add(_in, 32)\n        }\n\n        out_ = RLPItem({ length: _in.length, ptr: ptr });\n    }\n\n    /// @notice Reads an RLP list value into a list of RLP items.\n    /// @param _in RLP list value.\n    /// @return out_ Decoded RLP list items.\n    function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory out_) {\n        (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);\n\n        require(itemType == RLPItemType.LIST_ITEM, \"RLPReader: decoded item type for list is not a list item\");\n\n        require(listOffset + listLength == _in.length, \"RLPReader: list item has an invalid data remainder\");\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        out_ = new RLPItem[](MAX_LIST_LENGTH);\n\n        uint256 itemCount = 0;\n        uint256 offset = listOffset;\n        while (offset < _in.length) {\n            (uint256 itemOffset, uint256 itemLength,) = _decodeLength(\n                RLPItem({ length: _in.length - offset, ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset) })\n            );\n\n            // We don't need to check itemCount < out.length explicitly because Solidity already\n            // handles this check on our behalf, we'd just be wasting gas.\n            out_[itemCount] = RLPItem({\n                length: itemLength + itemOffset,\n                ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_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\n    /// @notice Reads an RLP list value into a list of RLP items.\n    /// @param _in RLP list value.\n    /// @return out_ Decoded RLP list items.\n    function readList(bytes memory _in) internal pure returns (RLPItem[] memory out_) {\n        out_ = readList(toRLPItem(_in));\n    }\n\n    /// @notice Reads an RLP bytes value into bytes.\n    /// @param _in RLP bytes value.\n    /// @return out_ Decoded bytes.\n    function readBytes(RLPItem memory _in) internal pure returns (bytes memory out_) {\n        (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n        require(itemType == RLPItemType.DATA_ITEM, \"RLPReader: decoded item type for bytes is not a data item\");\n\n        require(_in.length == itemOffset + itemLength, \"RLPReader: bytes value contains an invalid remainder\");\n\n        out_ = _copy(_in.ptr, itemOffset, itemLength);\n    }\n\n    /// @notice Reads an RLP bytes value into bytes.\n    /// @param _in RLP bytes value.\n    /// @return out_ Decoded bytes.\n    function readBytes(bytes memory _in) internal pure returns (bytes memory out_) {\n        out_ = readBytes(toRLPItem(_in));\n    }\n\n    /// @notice Reads the raw bytes of an RLP item.\n    /// @param _in RLP item to read.\n    /// @return out_ Raw RLP bytes.\n    function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory out_) {\n        out_ = _copy(_in.ptr, 0, _in.length);\n    }\n\n    /// @notice Decodes the length of an RLP item.\n    /// @param _in RLP item to decode.\n    /// @return offset_ Offset of the encoded data.\n    /// @return length_ Length of the encoded data.\n    /// @return type_ RLP item type (LIST_ITEM or DATA_ITEM).\n    function _decodeLength(RLPItem memory _in)\n        private\n        pure\n        returns (uint256 offset_, uint256 length_, RLPItemType type_)\n    {\n        // Short-circuit if there's nothing to decode, note that we perform this check when\n        // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass\n        // that function and create an RLP item directly. So we need to check this anyway.\n        require(_in.length > 0, \"RLPReader: length of an RLP item must be greater than zero to be decodable\");\n\n        MemoryPointer ptr = _in.ptr;\n        uint256 prefix;\n        assembly {\n            prefix := byte(0, mload(ptr))\n        }\n\n        if (prefix <= 0x7f) {\n            // Single byte.\n            return (0, 1, RLPItemType.DATA_ITEM);\n        } else if (prefix <= 0xb7) {\n            // Short string.\n\n            // slither-disable-next-line variable-scope\n            uint256 strLen = prefix - 0x80;\n\n            require(\n                _in.length > strLen, \"RLPReader: length of content must be greater than string length (short string)\"\n            );\n\n            bytes1 firstByteOfContent;\n            assembly {\n                firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n            }\n\n            require(\n                strLen != 1 || firstByteOfContent >= 0x80,\n                \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (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                \"RLPReader: length of content must be > than length of string length (long string)\"\n            );\n\n            bytes1 firstByteOfContent;\n            assembly {\n                firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n            }\n\n            require(\n                firstByteOfContent != 0x00, \"RLPReader: length of content must not have any leading zeros (long string)\"\n            );\n\n            uint256 strLen;\n            assembly {\n                strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))\n            }\n\n            require(strLen > 55, \"RLPReader: length of content must be greater than 55 bytes (long string)\");\n\n            require(\n                _in.length > lenOfStrLen + strLen,\n                \"RLPReader: length of content must be greater than total length (long string)\"\n            );\n\n            return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n        } else if (prefix <= 0xf7) {\n            // Short list.\n            // slither-disable-next-line variable-scope\n            uint256 listLen = prefix - 0xc0;\n\n            require(_in.length > listLen, \"RLPReader: length of content must be greater than list length (short list)\");\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                \"RLPReader: length of content must be > than length of list length (long list)\"\n            );\n\n            bytes1 firstByteOfContent;\n            assembly {\n                firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n            }\n\n            require(\n                firstByteOfContent != 0x00, \"RLPReader: length of content must not have any leading zeros (long list)\"\n            );\n\n            uint256 listLen;\n            assembly {\n                listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))\n            }\n\n            require(listLen > 55, \"RLPReader: length of content must be greater than 55 bytes (long list)\");\n\n            require(\n                _in.length > lenOfListLen + listLen,\n                \"RLPReader: length of content must be greater than total length (long list)\"\n            );\n\n            return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n        }\n    }\n\n    /// @notice 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 out_ Copied bytes.\n    function _copy(MemoryPointer _src, uint256 _offset, uint256 _length) private pure returns (bytes memory out_) {\n        out_ = new bytes(_length);\n        if (_length == 0) {\n            return out_;\n        }\n\n        // Mostly based on Solidity's copy_memory_to_memory:\n        // solhint-disable max-line-length\n        // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114\n        uint256 src = MemoryPointer.unwrap(_src) + _offset;\n        assembly {\n            let dest := add(out_, 32)\n            let i := 0\n            for { } lt(i, _length) { i := add(i, 32) } { mstore(add(dest, i), mload(add(src, i))) }\n\n            if gt(i, _length) { mstore(add(dest, _length), 0) }\n        }\n    }\n}\n"
      },
      "@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPWriter.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\n/// @title RLPWriter\n/// @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\n///         RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\n///         modifications to improve legibility.\nlibrary RLPWriter {\n    /// @notice RLP encodes a byte string.\n    /// @param _in The byte string to encode.\n    /// @return out_ The RLP encoded string in bytes.\n    function writeBytes(bytes memory _in) internal pure returns (bytes memory out_) {\n        if (_in.length == 1 && uint8(_in[0]) < 128) {\n            out_ = _in;\n        } else {\n            out_ = abi.encodePacked(_writeLength(_in.length, 128), _in);\n        }\n    }\n\n    /// @notice RLP encodes a list of RLP encoded byte byte strings.\n    /// @param _in The list of RLP encoded byte strings.\n    /// @return list_ The RLP encoded list of items in bytes.\n    function writeList(bytes[] memory _in) internal pure returns (bytes memory list_) {\n        list_ = _flatten(_in);\n        list_ = abi.encodePacked(_writeLength(list_.length, 192), list_);\n    }\n\n    /// @notice RLP encodes a string.\n    /// @param _in The string to encode.\n    /// @return out_ The RLP encoded string in bytes.\n    function writeString(string memory _in) internal pure returns (bytes memory out_) {\n        out_ = writeBytes(bytes(_in));\n    }\n\n    /// @notice RLP encodes an address.\n    /// @param _in The address to encode.\n    /// @return out_ The RLP encoded address in bytes.\n    function writeAddress(address _in) internal pure returns (bytes memory out_) {\n        out_ = writeBytes(abi.encodePacked(_in));\n    }\n\n    /// @notice RLP encodes a uint.\n    /// @param _in The uint256 to encode.\n    /// @return out_ The RLP encoded uint256 in bytes.\n    function writeUint(uint256 _in) internal pure returns (bytes memory out_) {\n        out_ = writeBytes(_toBinary(_in));\n    }\n\n    /// @notice RLP encodes a bool.\n    /// @param _in The bool to encode.\n    /// @return out_ The RLP encoded bool in bytes.\n    function writeBool(bool _in) internal pure returns (bytes memory out_) {\n        out_ = new bytes(1);\n        out_[0] = (_in ? bytes1(0x01) : bytes1(0x80));\n    }\n\n    /// @notice Encode the first byte and then 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 out_ RLP encoded bytes.\n    function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory out_) {\n        if (_len < 56) {\n            out_ = new bytes(1);\n            out_[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            out_ = new bytes(lenLen + 1);\n            out_[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\n            for (i = 1; i <= lenLen; i++) {\n                out_[i] = bytes1(uint8((_len / (256 ** (lenLen - i))) % 256));\n            }\n        }\n    }\n\n    /// @notice Encode integer in big endian binary form with no leading zeroes.\n    /// @param _x The integer to encode.\n    /// @return out_ RLP encoded bytes.\n    function _toBinary(uint256 _x) private pure returns (bytes memory out_) {\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        out_ = new bytes(32 - i);\n        for (uint256 j = 0; j < out_.length; j++) {\n            out_[j] = b[i++];\n        }\n    }\n\n    /// @custom:attribution https://github.com/Arachnid/solidity-stringutils\n    /// @notice Copies a piece of memory to another location.\n    /// @param _dest Destination location.\n    /// @param _src  Source location.\n    /// @param _len  Length of memory to copy.\n    function _memcpy(uint256 _dest, uint256 _src, uint256 _len) private pure {\n        uint256 dest = _dest;\n        uint256 src = _src;\n        uint256 len = _len;\n\n        for (; len >= 32; len -= 32) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n            dest += 32;\n            src += 32;\n        }\n\n        uint256 mask;\n        unchecked {\n            mask = 256 ** (32 - len) - 1;\n        }\n        assembly {\n            let srcpart := and(mload(src), not(mask))\n            let destpart := and(mload(dest), mask)\n            mstore(dest, or(destpart, srcpart))\n        }\n    }\n\n    /// @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\n    /// @notice Flattens a list of byte strings into one byte string.\n    /// @param _list List of byte strings to flatten.\n    /// @return out_ The flattened byte string.\n    function _flatten(bytes[] memory _list) private pure returns (bytes memory out_) {\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        out_ = new bytes(len);\n        uint256 flattenedPtr;\n        assembly {\n            flattenedPtr := add(out_, 0x20)\n        }\n\n        for (i = 0; i < _list.length; i++) {\n            bytes memory item = _list[i];\n\n            uint256 listPtr;\n            assembly {\n                listPtr := add(item, 0x20)\n            }\n\n            _memcpy(flattenedPtr, listPtr, item.length);\n            flattenedPtr += _list[i].length;\n        }\n    }\n}\n"
      },
      "@eth-optimism/contracts-bedrock/src/libraries/Types.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Types\n/// @notice Contains various types used throughout the Optimism contract system.\nlibrary Types {\n    /// @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\n    ///         timestamp that the output root is posted. This timestamp is used to verify that the\n    ///         finalization period has passed since the output root was submitted.\n    /// @custom:field outputRoot    Hash of the L2 output.\n    /// @custom:field timestamp     Timestamp of the L1 block that the output root was submitted in.\n    /// @custom:field l2BlockNumber L2 block number that the output corresponds to.\n    struct OutputProposal {\n        bytes32 outputRoot;\n        uint128 timestamp;\n        uint128 l2BlockNumber;\n    }\n\n    /// @notice Struct representing the elements that are hashed together to generate an output root\n    ///         which itself represents a snapshot of the L2 state.\n    /// @custom:field version                  Version of the output root.\n    /// @custom:field stateRoot                Root of the state trie at the block of this output.\n    /// @custom:field messagePasserStorageRoot Root of the message passer storage trie.\n    /// @custom:field latestBlockhash          Hash of the block this output was generated from.\n    struct OutputRootProof {\n        bytes32 version;\n        bytes32 stateRoot;\n        bytes32 messagePasserStorageRoot;\n        bytes32 latestBlockhash;\n    }\n\n    /// @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\n    ///         user (as opposed to a system deposit transaction generated by the system).\n    /// @custom:field from        Address of the sender of the transaction.\n    /// @custom:field to          Address of the recipient of the transaction.\n    /// @custom:field isCreation  True if the transaction is a contract creation.\n    /// @custom:field value       Value to send to the recipient.\n    /// @custom:field mint        Amount of ETH to mint.\n    /// @custom:field gasLimit    Gas limit of the transaction.\n    /// @custom:field data        Data of the transaction.\n    /// @custom:field l1BlockHash Hash of the block the transaction was submitted in.\n    /// @custom:field logIndex    Index of the log in the block the transaction was submitted in.\n    struct UserDepositTransaction {\n        address from;\n        address to;\n        bool isCreation;\n        uint256 value;\n        uint256 mint;\n        uint64 gasLimit;\n        bytes data;\n        bytes32 l1BlockHash;\n        uint256 logIndex;\n    }\n\n    /// @notice Struct representing a withdrawal transaction.\n    /// @custom:field nonce    Nonce of the withdrawal transaction\n    /// @custom:field sender   Address of the sender of the transaction.\n    /// @custom:field target   Address of the recipient of the transaction.\n    /// @custom:field value    Value to send to the recipient.\n    /// @custom:field gasLimit Gas limit of the transaction.\n    /// @custom:field data     Data of the transaction.\n    struct WithdrawalTransaction {\n        uint256 nonce;\n        address sender;\n        address target;\n        uint256 value;\n        uint256 gasLimit;\n        bytes data;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\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 or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\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    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\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    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\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            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert FailedInnerCall();\n        }\n    }\n}\n"
      },
      "contracts/OPVerifier.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { IEVMVerifier } from \"@ensdomains/evm-verifier/contracts/IEVMVerifier.sol\";\nimport { RLPReader } from \"@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol\";\nimport { StateProof, EVMProofHelper } from \"@ensdomains/evm-verifier/contracts/EVMProofHelper.sol\";\nimport { Types } from \"@eth-optimism/contracts-bedrock/src/libraries/Types.sol\";\nimport { Hashing } from \"@eth-optimism/contracts-bedrock/src/libraries/Hashing.sol\";\n\nstruct OPWitnessData {\n    uint256 l2OutputIndex;\n    Types.OutputRootProof outputRootProof;\n}\n\ninterface IL2OutputOracle {\n    function getL2Output(uint256 _l2OutputIndex) external view returns (Types.OutputProposal memory);\n}\n\ncontract OPVerifier is IEVMVerifier {\n    error OutputRootMismatch(uint256 l2OutputIndex, bytes32 expected, bytes32 actual);\n\n    IL2OutputOracle public opOracle;\n    string[] _gatewayURLs;\n\n    constructor(string[] memory urls, address outputOracle) {\n        _gatewayURLs = urls;\n        opOracle = IL2OutputOracle(outputOracle);\n    }\n\n    function gatewayURLs() external view returns(string[] memory) {\n        return _gatewayURLs;\n    }\n\n    function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values) {\n        (OPWitnessData memory opData, StateProof memory stateProof) = abi.decode(proof, (OPWitnessData, StateProof));\n        Types.OutputProposal memory l2out = opOracle.getL2Output(opData.l2OutputIndex);\n        bytes32 expectedRoot = Hashing.hashOutputRootProof(opData.outputRootProof);\n        if(l2out.outputRoot != expectedRoot) {\n            revert OutputRootMismatch(opData.l2OutputIndex, expectedRoot, l2out.outputRoot);\n        }\n        return EVMProofHelper.getStorageValues(target, commands, constants, opData.outputRootProof.stateRoot, stateProof);\n    }\n}\n"
      },
      "contracts/test/TestL1.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { EVMFetcher } from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol';\nimport { EVMFetchTarget } from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol';\nimport { IEVMVerifier } from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol';\n\ncontract TestL1 is EVMFetchTarget {\n    using EVMFetcher for EVMFetcher.EVMFetchRequest;\n\n    IEVMVerifier verifier;                  // Slot 0\n    address target;\n\n    constructor(IEVMVerifier _verifier, address _target) {\n        verifier = _verifier;\n        target = _target;\n    }\n\n    function getLatest() public view returns(uint256) {\n        EVMFetcher.newFetchRequest(verifier, target)\n            .getStatic(0)\n            .fetch(this.getLatestCallback.selector, \"\");\n    }\n\n    function getLatestCallback(bytes[] memory values, bytes memory) public pure returns(uint256) {\n        return abi.decode(values[0], (uint256));\n    }\n\n    function getName() public view returns(string memory) {\n        EVMFetcher.newFetchRequest(verifier, target)\n            .getDynamic(1)\n            .fetch(this.getNameCallback.selector, \"\");\n    }\n\n    function getNameCallback(bytes[] memory values, bytes memory) public pure returns(string memory) {\n        return string(values[0]);\n    }\n\n    function getHighscorer(uint256 idx) public view returns(string memory) {\n        EVMFetcher.newFetchRequest(verifier, target)\n            .getDynamic(3)\n                .element(idx)\n            .fetch(this.getHighscorerCallback.selector, \"\");\n    }\n\n    function getHighscorerCallback(bytes[] memory values, bytes memory) public pure returns(string memory) {\n        return string(values[0]);\n    }\n\n    function getLatestHighscore() public view returns(uint256) {\n        EVMFetcher.newFetchRequest(verifier, target)\n            .getStatic(0)\n            .getStatic(2)\n                .ref(0)\n            .fetch(this.getLatestHighscoreCallback.selector, \"\");\n    }\n\n    function getLatestHighscoreCallback(bytes[] memory values, bytes memory) public pure returns(uint256) {\n        return abi.decode(values[1], (uint256));\n    }\n\n    function getLatestHighscorer() public view returns(string memory) {\n        EVMFetcher.newFetchRequest(verifier, target)\n            .getStatic(0)\n            .getDynamic(3)\n                .ref(0)\n            .fetch(this.getLatestHighscorerCallback.selector, \"\");\n    }\n\n    function getLatestHighscorerCallback(bytes[] memory values, bytes memory) public pure returns(string memory) {\n        return string(values[1]);\n    }\n\n    function getNickname(string memory _name) public view returns(string memory) {\n        EVMFetcher.newFetchRequest(verifier, target)\n            .getDynamic(4)\n                .element(_name)\n            .fetch(this.getNicknameCallback.selector, \"\");\n    }\n\n    function getNicknameCallback(bytes[] memory values, bytes memory) public pure returns (string memory) {\n        return string(values[0]);\n    }\n\n    function getPrimaryNickname() public view returns(string memory) {\n        EVMFetcher.newFetchRequest(verifier, target)\n            .getDynamic(1)\n            .getDynamic(4)\n                .ref(0)\n            .fetch(this.getPrimaryNicknameCallback.selector, \"\");\n    }\n\n    function getPrimaryNicknameCallback(bytes[] memory values, bytes memory) public pure returns (string memory) {\n        return string(values[1]);\n    }\n\n    function getZero() public view returns(uint256) {\n        EVMFetcher.newFetchRequest(verifier, target)\n            .getStatic(5)\n            .fetch(this.getZeroCallback.selector, \"\");\n    }\n\n    function getZeroCallback(bytes[] memory values, bytes memory) public pure returns (uint256) {\n        return abi.decode(values[0], (uint256));\n    }\n}\n"
      },
      "contracts/test/TestL2.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\ncontract TestL2 {\n    uint256 latest;                         // Slot 0\n    string name;                            // Slot 1\n    mapping(uint256=>uint256) highscores;   // Slot 2\n    mapping(uint256=>string) highscorers;   // Slot 3\n    mapping(string=>string) realnames;      // Slot 4\n    uint256 zero;                           // Slot 5\n\n    constructor() {\n        latest = 42;\n        name = \"Satoshi\";\n        highscores[latest] = 12345;\n        highscorers[latest] = \"Hal Finney\";\n        highscorers[1] = \"Hubert Blaine Wolfeschlegelsteinhausenbergerdorff Sr.\";\n        realnames[\"Money Skeleton\"] = \"Vitalik Buterin\";\n        realnames[\"Satoshi\"] = \"Hal Finney\";\n    }\n}"
      }
    },
    "settings": {
      "evmVersion": "paris",
      "optimizer": {
        "enabled": false,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      }
    }
  }}