creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@ensdomains/ens-contracts/contracts/dnssec-oracle/BytesUtils.sol": {
        "content": "pragma solidity ^0.8.4;\n\nlibrary BytesUtils {\n    error OffsetOutOfBoundsError(uint256 offset, uint256 length);\n\n    /*\n     * @dev Returns the keccak-256 hash of a byte range.\n     * @param self The byte string to hash.\n     * @param offset The position to start hashing at.\n     * @param len The number of bytes to hash.\n     * @return The hash of the byte range.\n     */\n    function keccak(\n        bytes memory self,\n        uint256 offset,\n        uint256 len\n    ) internal pure returns (bytes32 ret) {\n        require(offset + len <= self.length);\n        assembly {\n            ret := keccak256(add(add(self, 32), offset), len)\n        }\n    }\n\n    /*\n     * @dev Returns a positive number if `other` comes lexicographically after\n     *      `self`, a negative number if it comes before, or zero if the\n     *      contents of the two bytes are equal.\n     * @param self The first bytes to compare.\n     * @param other The second bytes to compare.\n     * @return The result of the comparison.\n     */\n    function compare(\n        bytes memory self,\n        bytes memory other\n    ) internal pure returns (int256) {\n        return compare(self, 0, self.length, other, 0, other.length);\n    }\n\n    /*\n     * @dev Returns a positive number if `other` comes lexicographically after\n     *      `self`, a negative number if it comes before, or zero if the\n     *      contents of the two bytes are equal. Comparison is done per-rune,\n     *      on unicode codepoints.\n     * @param self The first bytes to compare.\n     * @param offset The offset of self.\n     * @param len    The length of self.\n     * @param other The second bytes to compare.\n     * @param otheroffset The offset of the other string.\n     * @param otherlen    The length of the other string.\n     * @return The result of the comparison.\n     */\n    function compare(\n        bytes memory self,\n        uint256 offset,\n        uint256 len,\n        bytes memory other,\n        uint256 otheroffset,\n        uint256 otherlen\n    ) internal pure returns (int256) {\n        if (offset + len > self.length) {\n            revert OffsetOutOfBoundsError(offset + len, self.length);\n        }\n        if (otheroffset + otherlen > other.length) {\n            revert OffsetOutOfBoundsError(otheroffset + otherlen, other.length);\n        }\n\n        uint256 shortest = len;\n        if (otherlen < len) shortest = otherlen;\n\n        uint256 selfptr;\n        uint256 otherptr;\n\n        assembly {\n            selfptr := add(self, add(offset, 32))\n            otherptr := add(other, add(otheroffset, 32))\n        }\n        for (uint256 idx = 0; idx < shortest; idx += 32) {\n            uint256 a;\n            uint256 b;\n            assembly {\n                a := mload(selfptr)\n                b := mload(otherptr)\n            }\n            if (a != b) {\n                // Mask out irrelevant bytes and check again\n                uint256 mask;\n                if (shortest - idx >= 32) {\n                    mask = type(uint256).max;\n                } else {\n                    mask = ~(2 ** (8 * (idx + 32 - shortest)) - 1);\n                }\n                int256 diff = int256(a & mask) - int256(b & mask);\n                if (diff != 0) return diff;\n            }\n            selfptr += 32;\n            otherptr += 32;\n        }\n\n        return int256(len) - int256(otherlen);\n    }\n\n    /*\n     * @dev Returns true if the two byte ranges are equal.\n     * @param self The first byte range to compare.\n     * @param offset The offset into the first byte range.\n     * @param other The second byte range to compare.\n     * @param otherOffset The offset into the second byte range.\n     * @param len The number of bytes to compare\n     * @return True if the byte ranges are equal, false otherwise.\n     */\n    function equals(\n        bytes memory self,\n        uint256 offset,\n        bytes memory other,\n        uint256 otherOffset,\n        uint256 len\n    ) internal pure returns (bool) {\n        return keccak(self, offset, len) == keccak(other, otherOffset, len);\n    }\n\n    /*\n     * @dev Returns true if the two byte ranges are equal with offsets.\n     * @param self The first byte range to compare.\n     * @param offset The offset into the first byte range.\n     * @param other The second byte range to compare.\n     * @param otherOffset The offset into the second byte range.\n     * @return True if the byte ranges are equal, false otherwise.\n     */\n    function equals(\n        bytes memory self,\n        uint256 offset,\n        bytes memory other,\n        uint256 otherOffset\n    ) internal pure returns (bool) {\n        return\n            keccak(self, offset, self.length - offset) ==\n            keccak(other, otherOffset, other.length - otherOffset);\n    }\n\n    /*\n     * @dev Compares a range of 'self' to all of 'other' and returns True iff\n     *      they are equal.\n     * @param self The first byte range to compare.\n     * @param offset The offset into the first byte range.\n     * @param other The second byte range to compare.\n     * @return True if the byte ranges are equal, false otherwise.\n     */\n    function equals(\n        bytes memory self,\n        uint256 offset,\n        bytes memory other\n    ) internal pure returns (bool) {\n        return\n            self.length == offset + other.length &&\n            equals(self, offset, other, 0, other.length);\n    }\n\n    /*\n     * @dev Returns true if the two byte ranges are equal.\n     * @param self The first byte range to compare.\n     * @param other The second byte range to compare.\n     * @return True if the byte ranges are equal, false otherwise.\n     */\n    function equals(\n        bytes memory self,\n        bytes memory other\n    ) internal pure returns (bool) {\n        return\n            self.length == other.length &&\n            equals(self, 0, other, 0, self.length);\n    }\n\n    /*\n     * @dev Returns the 8-bit number at the specified index of self.\n     * @param self The byte string.\n     * @param idx The index into the bytes\n     * @return The specified 8 bits of the string, interpreted as an integer.\n     */\n    function readUint8(\n        bytes memory self,\n        uint256 idx\n    ) internal pure returns (uint8 ret) {\n        return uint8(self[idx]);\n    }\n\n    /*\n     * @dev Returns the 16-bit number at the specified index of self.\n     * @param self The byte string.\n     * @param idx The index into the bytes\n     * @return The specified 16 bits of the string, interpreted as an integer.\n     */\n    function readUint16(\n        bytes memory self,\n        uint256 idx\n    ) internal pure returns (uint16 ret) {\n        require(idx + 2 <= self.length);\n        assembly {\n            ret := and(mload(add(add(self, 2), idx)), 0xFFFF)\n        }\n    }\n\n    /*\n     * @dev Returns the 32-bit number at the specified index of self.\n     * @param self The byte string.\n     * @param idx The index into the bytes\n     * @return The specified 32 bits of the string, interpreted as an integer.\n     */\n    function readUint32(\n        bytes memory self,\n        uint256 idx\n    ) internal pure returns (uint32 ret) {\n        require(idx + 4 <= self.length);\n        assembly {\n            ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF)\n        }\n    }\n\n    /*\n     * @dev Returns the 32 byte value at the specified index of self.\n     * @param self The byte string.\n     * @param idx The index into the bytes\n     * @return The specified 32 bytes of the string.\n     */\n    function readBytes32(\n        bytes memory self,\n        uint256 idx\n    ) internal pure returns (bytes32 ret) {\n        require(idx + 32 <= self.length);\n        assembly {\n            ret := mload(add(add(self, 32), idx))\n        }\n    }\n\n    /*\n     * @dev Returns the 32 byte value at the specified index of self.\n     * @param self The byte string.\n     * @param idx The index into the bytes\n     * @return The specified 32 bytes of the string.\n     */\n    function readBytes20(\n        bytes memory self,\n        uint256 idx\n    ) internal pure returns (bytes20 ret) {\n        require(idx + 20 <= self.length);\n        assembly {\n            ret := and(\n                mload(add(add(self, 32), idx)),\n                0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000\n            )\n        }\n    }\n\n    /*\n     * @dev Returns the n byte value at the specified index of self.\n     * @param self The byte string.\n     * @param idx The index into the bytes.\n     * @param len The number of bytes.\n     * @return The specified 32 bytes of the string.\n     */\n    function readBytesN(\n        bytes memory self,\n        uint256 idx,\n        uint256 len\n    ) internal pure returns (bytes32 ret) {\n        require(len <= 32);\n        require(idx + len <= self.length);\n        assembly {\n            let mask := not(sub(exp(256, sub(32, len)), 1))\n            ret := and(mload(add(add(self, 32), idx)), mask)\n        }\n    }\n\n    function memcpy(uint256 dest, uint256 src, uint256 len) private pure {\n        // Copy word-length chunks while possible\n        for (; len >= 32; len -= 32) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n            dest += 32;\n            src += 32;\n        }\n\n        // Copy remaining bytes\n        unchecked {\n            uint256 mask = (256 ** (32 - len)) - 1;\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    /*\n     * @dev Copies a substring into a new byte string.\n     * @param self The byte string to copy from.\n     * @param offset The offset to start copying at.\n     * @param len The number of bytes to copy.\n     */\n    function substring(\n        bytes memory self,\n        uint256 offset,\n        uint256 len\n    ) internal pure returns (bytes memory) {\n        require(offset + len <= self.length);\n\n        bytes memory ret = new bytes(len);\n        uint256 dest;\n        uint256 src;\n\n        assembly {\n            dest := add(ret, 32)\n            src := add(add(self, 32), offset)\n        }\n        memcpy(dest, src, len);\n\n        return ret;\n    }\n\n    // Maps characters from 0x30 to 0x7A to their base32 values.\n    // 0xFF represents invalid characters in that range.\n    bytes constant base32HexTable =\n        hex\"00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\";\n\n    /**\n     * @dev Decodes unpadded base32 data of up to one word in length.\n     * @param self The data to decode.\n     * @param off Offset into the string to start at.\n     * @param len Number of characters to decode.\n     * @return The decoded data, left aligned.\n     */\n    function base32HexDecodeWord(\n        bytes memory self,\n        uint256 off,\n        uint256 len\n    ) internal pure returns (bytes32) {\n        require(len <= 52);\n\n        uint256 ret = 0;\n        uint8 decoded;\n        for (uint256 i = 0; i < len; i++) {\n            bytes1 char = self[off + i];\n            require(char >= 0x30 && char <= 0x7A);\n            decoded = uint8(base32HexTable[uint256(uint8(char)) - 0x30]);\n            require(decoded <= 0x20);\n            if (i == len - 1) {\n                break;\n            }\n            ret = (ret << 5) | decoded;\n        }\n\n        uint256 bitlen = len * 5;\n        if (len % 8 == 0) {\n            // Multiple of 8 characters, no padding\n            ret = (ret << 5) | decoded;\n        } else if (len % 8 == 2) {\n            // Two extra characters - 1 byte\n            ret = (ret << 3) | (decoded >> 2);\n            bitlen -= 2;\n        } else if (len % 8 == 4) {\n            // Four extra characters - 2 bytes\n            ret = (ret << 1) | (decoded >> 4);\n            bitlen -= 4;\n        } else if (len % 8 == 5) {\n            // Five extra characters - 3 bytes\n            ret = (ret << 4) | (decoded >> 1);\n            bitlen -= 1;\n        } else if (len % 8 == 7) {\n            // Seven extra characters - 4 bytes\n            ret = (ret << 2) | (decoded >> 3);\n            bitlen -= 3;\n        } else {\n            revert();\n        }\n\n        return bytes32(ret << (256 - bitlen));\n    }\n\n    /**\n     * @dev Finds the first occurrence of the byte `needle` in `self`.\n     * @param self The string to search\n     * @param off The offset to start searching at\n     * @param len The number of bytes to search\n     * @param needle The byte to search for\n     * @return The offset of `needle` in `self`, or 2**256-1 if it was not found.\n     */\n    function find(\n        bytes memory self,\n        uint256 off,\n        uint256 len,\n        bytes1 needle\n    ) internal pure returns (uint256) {\n        for (uint256 idx = off; idx < off + len; idx++) {\n            if (self[idx] == needle) {\n                return idx;\n            }\n        }\n        return type(uint256).max;\n    }\n}\n"
      },
      "@ensdomains/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\n/**\n * Interface for the legacy (ETH-only) addr function.\n */\ninterface IAddrResolver {\n    event AddrChanged(bytes32 indexed node, address a);\n\n    /**\n     * Returns the address associated with an ENS node.\n     * @param node The ENS node to query.\n     * @return The associated address.\n     */\n    function addr(bytes32 node) external view returns (address payable);\n}\n"
      },
      "@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface INameResolver {\n    event NameChanged(bytes32 indexed node, string name);\n\n    /**\n     * Returns the name associated with an ENS node, for reverse records.\n     * Defined in EIP181.\n     * @param node The ENS node to query.\n     * @return The associated name.\n     */\n    function name(bytes32 node) external view returns (string memory);\n}\n"
      },
      "@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface ITextResolver {\n    event TextChanged(\n        bytes32 indexed node,\n        string indexed indexedKey,\n        string key,\n        string value\n    );\n\n    /**\n     * Returns the text data associated with an ENS node and key.\n     * @param node The ENS node to query.\n     * @param key The text data key to query.\n     * @return The associated text data.\n     */\n    function text(\n        bytes32 node,\n        string calldata key\n    ) external view returns (string memory);\n}\n"
      },
      "@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/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"
      },
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../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 * The initial owner is set to the address provided by the deployer. This can\n * 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    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\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 the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(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        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\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"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\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    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
      },
      "contracts/l1/Dm3NameRegistrarEVMFetcher.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport {EVMFetcher} from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol';\nimport {EVMFetchTarget} from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol';\nimport {BytesUtils} from '@ensdomains/ens-contracts/contracts/dnssec-oracle/BytesUtils.sol';\nimport {IAddrResolver} from '@ensdomains/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol';\nimport {ITextResolver} from '@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol';\nimport {INameResolver} from '@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol';\nimport {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './strings.sol';\n\ncontract Dm3NameRegistrarEVMFetcher is EVMFetchTarget, Ownable {\n    using EVMFetcher for EVMFetcher.EVMFetchRequest;\n    using BytesUtils for bytes;\n    using strings for *;\n\n    IEVMVerifier public verifier;\n    address public target;\n    string public parentDomain;\n\n    uint256 private constant RECORD_VERSIONS_SLOT = 201;\n    uint256 private constant PARENT_NODE_SLOT = 202;\n    uint256 private constant OWNER_SLOT = 203;\n    uint256 private constant REVERSE_SLOT = 204;\n    uint256 private constant TEXTS_SLOT = 205;\n\n    error UnknownSelector();\n\n    /**\n     * @notice Creates a new Dm3NameRegistrarEVMFetcher contract. Tha can be used to fetch data from the Dm3NameRegistrar contract using CCIP.\n     * @param _verifier The EVM Verifier to be used by this contract.\n     * @param _target The target address to be used by this contract.\n     * @param _parentDomain The parent domain to be used by this contract.\n     */\n    constructor(\n        IEVMVerifier _verifier,\n        address _target,\n        string memory _parentDomain\n    ) Ownable(msg.sender) {\n        verifier = _verifier;\n        target = _target;\n        parentDomain = _parentDomain;\n    }\n    /**\n     * @notice Sets the EVM Verifier.\n     * @dev Can only be called by the contract owner.\n     * @param _verifier The new EVM Verifier.\n     */\n    function setVerifier(IEVMVerifier _verifier) external onlyOwner {\n        verifier = _verifier;\n    }\n    /**\n     * @notice Sets the target address.\n     * @dev Can only be called by the contract owner.\n     * @param _target The new target address.\n     */\n    function setTarget(address _target) external onlyOwner {\n        target = _target;\n    }\n\n    /**\n     * @notice Sets the parent domain.\n     * @dev Can only be called by the contract owner.\n     * @param _parentDomain The new parent domain.\n     */\n    function setParentDomain(string memory _parentDomain) external onlyOwner {\n        parentDomain = _parentDomain;\n    }\n    /**\n     * @notice Resolves the given name and data.\n     * @param data The data to resolve.\n     * @return result The result of the resolution.\n     */\n    function resolve(\n        bytes calldata,\n        bytes calldata data\n    ) external view returns (bytes memory result) {\n        bytes4 selector = bytes4(data);\n\n        if (selector == INameResolver.name.selector) {\n            bytes32 node = abi.decode(data[4:], (bytes32));\n            return _name(node);\n        }\n        if (selector == ITextResolver.text.selector) {\n            (bytes32 node, string memory key) = abi.decode(\n                data[4:],\n                (bytes32, string)\n            );\n            return bytes(_text(node, key));\n        }\n        if (selector == IAddrResolver.addr.selector) {\n            bytes32 node = abi.decode(data[4:], (bytes32));\n            return _addr(node);\n        }\n        //Revert if the selector is unknown\n        revert UnknownSelector();\n    }\n    /**\n     * @notice Resolves the address for the given node.\n     * @param node The node to resolve the address for.\n     */\n    function _addr(bytes32 node) private view returns (bytes memory) {\n        EVMFetcher\n            .newFetchRequest(verifier, target)\n            .getStatic(OWNER_SLOT)\n            .element(node)\n            .fetch(this.addrCallback.selector, '');\n    }\n    /**\n     * @notice Resolves the name for the given node.\n     * @param node The node to resolve the name for.\n     */\n    function _name(bytes32 node) private view returns (bytes memory) {\n        EVMFetcher\n            .newFetchRequest(verifier, target)\n            .getStatic(PARENT_NODE_SLOT)\n            .getDynamic(REVERSE_SLOT)\n            .element(node)\n            .fetch(this.nameCallback.selector, '');\n    }\n\n    /**\n     * @notice Resolves the text for the given node and key.\n     * @param node The node to resolve the text for.\n     * @param key The key to resolve the text for.\n     */\n    function _text(\n        bytes32 node,\n        string memory key\n    ) private view returns (bytes memory) {\n        EVMFetcher\n            .newFetchRequest(verifier, target)\n            .getStatic(RECORD_VERSIONS_SLOT)\n            .element(node)\n            .getDynamic(TEXTS_SLOT)\n            .ref(0)\n            .element(node)\n            .element(key)\n            .fetch(this.textCallback.selector, '');\n    }\n    /**\n     * @notice Callback function for text resolution.\n     * @param values The values to encode.\n     * @return The value of the text record abi encoded.\n     */\n    function textCallback(\n        bytes[] memory values,\n        bytes memory\n    ) public pure returns (bytes memory) {\n        return abi.encode(string(values[1]));\n    }\n    /**\n     * @notice Callback function for name resolution.\n     * @param values The values to encode.\n     * @return The name registered with the parent domain abi encoded.\n     */\n    function nameCallback(\n        bytes[] memory values,\n        bytes memory\n    ) public view returns (bytes memory) {\n        strings.slice[] memory s = new strings.slice[](3);\n        //The label i.e alice\n        s[0] = string(values[1]).toSlice();\n        //Separator\n        s[1] = '.'.toSlice();\n        //The parent domain i.e example.com\n        s[2] = parentDomain.toSlice();\n        return abi.encode(''.toSlice().join(s));\n    }\n    /**\n     * @notice Callback function for address resolution.\n     * @param values The values to encode.\n     */\n    function addrCallback(\n        bytes[] memory values,\n        bytes memory\n    ) public pure returns (bytes memory) {\n        return abi.encode(address(uint160(uint256(bytes32(values[0])))));\n    }\n}\n"
      },
      "contracts/l1/strings.sol": {
        "content": "/*\n * @title String & slice utility library for Solidity contracts.\n * @author Nick Johnson <arachnid@notdot.net>\n *\n * @dev Functionality in this library is largely implemented using an\n *      abstraction called a 'slice'. A slice represents a part of a string -\n *      anything from the entire string to a single character, or even no\n *      characters at all (a 0-length slice). Since a slice only has to specify\n *      an offset and a length, copying and manipulating slices is a lot less\n *      expensive than copying and manipulating the strings they reference.\n *\n *      To further reduce gas costs, most functions on slice that need to return\n *      a slice modify the original one instead of allocating a new one; for\n *      instance, `s.split(\".\")` will return the text up to the first '.',\n *      modifying s to only contain the remainder of the string after the '.'.\n *      In situations where you do not want to modify the original slice, you\n *      can make a copy first with `.copy()`, for example:\n *      `s.copy().split(\".\")`. Try and avoid using this idiom in loops; since\n *      Solidity has no memory management, it will result in allocating many\n *      short-lived slices that are later discarded.\n *\n *      Functions that return two slices come in two versions: a non-allocating\n *      version that takes the second slice as an argument, modifying it in\n *      place, and an allocating version that allocates and returns the second\n *      slice; see `nextRune` for example.\n *\n *      Functions that have to copy string data will return strings rather than\n *      slices; these can be cast back to slices for further processing if\n *      required.\n *\n *      For convenience, some functions are provided with non-modifying\n *      variants that create a new slice and return both; for instance,\n *      `s.splitNew('.')` leaves s unmodified, and returns two values\n *      corresponding to the left and right parts of the string.\n */\n\npragma solidity ^0.8.0;\n\nlibrary strings {\n    struct slice {\n        uint _len;\n        uint _ptr;\n    }\n\n    function memcpy(uint dest, uint src, uint length) private pure {\n        // Copy word-length chunks while possible\n        for(; length >= 32; length -= 32) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n            dest += 32;\n            src += 32;\n        }\n\n        // Copy remaining bytes\n        uint mask = type(uint).max;\n        if (length > 0) {\n            mask = 256 ** (32 - length) - 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     * @dev Returns a slice containing the entire string.\n     * @param self The string to make a slice from.\n     * @return A newly allocated slice containing the entire string.\n     */\n    function toSlice(string memory self) internal pure returns (slice memory) {\n        uint ptr;\n        assembly {\n            ptr := add(self, 0x20)\n        }\n        return slice(bytes(self).length, ptr);\n    }\n\n    /*\n     * @dev Returns the length of a null-terminated bytes32 string.\n     * @param self The value to find the length of.\n     * @return The length of the string, from 0 to 32.\n     */\n    function len(bytes32 self) internal pure returns (uint) {\n        uint ret;\n        if (self == 0)\n            return 0;\n        if (uint(self) & type(uint128).max == 0) {\n            ret += 16;\n            self = bytes32(uint(self) / 0x100000000000000000000000000000000);\n        }\n        if (uint(self) & type(uint64).max == 0) {\n            ret += 8;\n            self = bytes32(uint(self) / 0x10000000000000000);\n        }\n        if (uint(self) & type(uint32).max == 0) {\n            ret += 4;\n            self = bytes32(uint(self) / 0x100000000);\n        }\n        if (uint(self) & type(uint16).max == 0) {\n            ret += 2;\n            self = bytes32(uint(self) / 0x10000);\n        }\n        if (uint(self) & type(uint8).max == 0) {\n            ret += 1;\n        }\n        return 32 - ret;\n    }\n\n    /*\n     * @dev Returns a slice containing the entire bytes32, interpreted as a\n     *      null-terminated utf-8 string.\n     * @param self The bytes32 value to convert to a slice.\n     * @return A new slice containing the value of the input argument up to the\n     *         first null.\n     */\n    function toSliceB32(bytes32 self) internal pure returns (slice memory ret) {\n        // Allocate space for `self` in memory, copy it there, and point ret at it\n        assembly {\n            let ptr := mload(0x40)\n            mstore(0x40, add(ptr, 0x20))\n            mstore(ptr, self)\n            mstore(add(ret, 0x20), ptr)\n        }\n        ret._len = len(self);\n    }\n\n    /*\n     * @dev Returns a new slice containing the same data as the current slice.\n     * @param self The slice to copy.\n     * @return A new slice containing the same data as `self`.\n     */\n    function copy(slice memory self) internal pure returns (slice memory) {\n        return slice(self._len, self._ptr);\n    }\n\n    /*\n     * @dev Copies a slice to a new string.\n     * @param self The slice to copy.\n     * @return A newly allocated string containing the slice's text.\n     */\n    function toString(slice memory self) internal pure returns (string memory) {\n        string memory ret = new string(self._len);\n        uint retptr;\n        assembly { retptr := add(ret, 32) }\n\n        memcpy(retptr, self._ptr, self._len);\n        return ret;\n    }\n\n    /*\n     * @dev Returns the length in runes of the slice. Note that this operation\n     *      takes time proportional to the length of the slice; avoid using it\n     *      in loops, and call `slice.empty()` if you only need to know whether\n     *      the slice is empty or not.\n     * @param self The slice to operate on.\n     * @return The length of the slice in runes.\n     */\n    function len(slice memory self) internal pure returns (uint l) {\n        // Starting at ptr-31 means the LSB will be the byte we care about\n        uint ptr = self._ptr - 31;\n        uint end = ptr + self._len;\n        for (l = 0; ptr < end; l++) {\n            uint8 b;\n            assembly { b := and(mload(ptr), 0xFF) }\n            if (b < 0x80) {\n                ptr += 1;\n            } else if(b < 0xE0) {\n                ptr += 2;\n            } else if(b < 0xF0) {\n                ptr += 3;\n            } else if(b < 0xF8) {\n                ptr += 4;\n            } else if(b < 0xFC) {\n                ptr += 5;\n            } else {\n                ptr += 6;\n            }\n        }\n    }\n\n    /*\n     * @dev Returns true if the slice is empty (has a length of 0).\n     * @param self The slice to operate on.\n     * @return True if the slice is empty, False otherwise.\n     */\n    function empty(slice memory self) internal pure returns (bool) {\n        return self._len == 0;\n    }\n\n    /*\n     * @dev Returns a positive number if `other` comes lexicographically after\n     *      `self`, a negative number if it comes before, or zero if the\n     *      contents of the two slices are equal. Comparison is done per-rune,\n     *      on unicode codepoints.\n     * @param self The first slice to compare.\n     * @param other The second slice to compare.\n     * @return The result of the comparison.\n     */\n    function compare(slice memory self, slice memory other) internal pure returns (int) {\n        uint shortest = self._len;\n        if (other._len < self._len)\n            shortest = other._len;\n\n        uint selfptr = self._ptr;\n        uint otherptr = other._ptr;\n        for (uint idx = 0; idx < shortest; idx += 32) {\n            uint a;\n            uint b;\n            assembly {\n                a := mload(selfptr)\n                b := mload(otherptr)\n            }\n            if (a != b) {\n                // Mask out irrelevant bytes and check again\n                uint mask = type(uint).max; // 0xffff...\n                if(shortest < 32) {\n                  mask = ~(2 ** (8 * (32 - shortest + idx)) - 1);\n                }\n                unchecked {\n                    uint diff = (a & mask) - (b & mask);\n                    if (diff != 0)\n                        return int(diff);\n                }\n            }\n            selfptr += 32;\n            otherptr += 32;\n        }\n        return int(self._len) - int(other._len);\n    }\n\n    /*\n     * @dev Returns true if the two slices contain the same text.\n     * @param self The first slice to compare.\n     * @param self The second slice to compare.\n     * @return True if the slices are equal, false otherwise.\n     */\n    function equals(slice memory self, slice memory other) internal pure returns (bool) {\n        return compare(self, other) == 0;\n    }\n\n    /*\n     * @dev Extracts the first rune in the slice into `rune`, advancing the\n     *      slice to point to the next rune and returning `self`.\n     * @param self The slice to operate on.\n     * @param rune The slice that will contain the first rune.\n     * @return `rune`.\n     */\n    function nextRune(slice memory self, slice memory rune) internal pure returns (slice memory) {\n        rune._ptr = self._ptr;\n\n        if (self._len == 0) {\n            rune._len = 0;\n            return rune;\n        }\n\n        uint l;\n        uint b;\n        // Load the first byte of the rune into the LSBs of b\n        assembly { b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) }\n        if (b < 0x80) {\n            l = 1;\n        } else if(b < 0xE0) {\n            l = 2;\n        } else if(b < 0xF0) {\n            l = 3;\n        } else {\n            l = 4;\n        }\n\n        // Check for truncated codepoints\n        if (l > self._len) {\n            rune._len = self._len;\n            self._ptr += self._len;\n            self._len = 0;\n            return rune;\n        }\n\n        self._ptr += l;\n        self._len -= l;\n        rune._len = l;\n        return rune;\n    }\n\n    /*\n     * @dev Returns the first rune in the slice, advancing the slice to point\n     *      to the next rune.\n     * @param self The slice to operate on.\n     * @return A slice containing only the first rune from `self`.\n     */\n    function nextRune(slice memory self) internal pure returns (slice memory ret) {\n        nextRune(self, ret);\n    }\n\n    /*\n     * @dev Returns the number of the first codepoint in the slice.\n     * @param self The slice to operate on.\n     * @return The number of the first codepoint in the slice.\n     */\n    function ord(slice memory self) internal pure returns (uint ret) {\n        if (self._len == 0) {\n            return 0;\n        }\n\n        uint word;\n        uint length;\n        uint divisor = 2 ** 248;\n\n        // Load the rune into the MSBs of b\n        assembly { word:= mload(mload(add(self, 32))) }\n        uint b = word / divisor;\n        if (b < 0x80) {\n            ret = b;\n            length = 1;\n        } else if(b < 0xE0) {\n            ret = b & 0x1F;\n            length = 2;\n        } else if(b < 0xF0) {\n            ret = b & 0x0F;\n            length = 3;\n        } else {\n            ret = b & 0x07;\n            length = 4;\n        }\n\n        // Check for truncated codepoints\n        if (length > self._len) {\n            return 0;\n        }\n\n        for (uint i = 1; i < length; i++) {\n            divisor = divisor / 256;\n            b = (word / divisor) & 0xFF;\n            if (b & 0xC0 != 0x80) {\n                // Invalid UTF-8 sequence\n                return 0;\n            }\n            ret = (ret * 64) | (b & 0x3F);\n        }\n\n        return ret;\n    }\n\n    /*\n     * @dev Returns the keccak-256 hash of the slice.\n     * @param self The slice to hash.\n     * @return The hash of the slice.\n     */\n    function keccak(slice memory self) internal pure returns (bytes32 ret) {\n        assembly {\n            ret := keccak256(mload(add(self, 32)), mload(self))\n        }\n    }\n\n    /*\n     * @dev Returns true if `self` starts with `needle`.\n     * @param self The slice to operate on.\n     * @param needle The slice to search for.\n     * @return True if the slice starts with the provided text, false otherwise.\n     */\n    function startsWith(slice memory self, slice memory needle) internal pure returns (bool) {\n        if (self._len < needle._len) {\n            return false;\n        }\n\n        if (self._ptr == needle._ptr) {\n            return true;\n        }\n\n        bool equal;\n        assembly {\n            let length := mload(needle)\n            let selfptr := mload(add(self, 0x20))\n            let needleptr := mload(add(needle, 0x20))\n            equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\n        }\n        return equal;\n    }\n\n    /*\n     * @dev If `self` starts with `needle`, `needle` is removed from the\n     *      beginning of `self`. Otherwise, `self` is unmodified.\n     * @param self The slice to operate on.\n     * @param needle The slice to search for.\n     * @return `self`\n     */\n    function beyond(slice memory self, slice memory needle) internal pure returns (slice memory) {\n        if (self._len < needle._len) {\n            return self;\n        }\n\n        bool equal = true;\n        if (self._ptr != needle._ptr) {\n            assembly {\n                let length := mload(needle)\n                let selfptr := mload(add(self, 0x20))\n                let needleptr := mload(add(needle, 0x20))\n                equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\n            }\n        }\n\n        if (equal) {\n            self._len -= needle._len;\n            self._ptr += needle._len;\n        }\n\n        return self;\n    }\n\n    /*\n     * @dev Returns true if the slice ends with `needle`.\n     * @param self The slice to operate on.\n     * @param needle The slice to search for.\n     * @return True if the slice starts with the provided text, false otherwise.\n     */\n    function endsWith(slice memory self, slice memory needle) internal pure returns (bool) {\n        if (self._len < needle._len) {\n            return false;\n        }\n\n        uint selfptr = self._ptr + self._len - needle._len;\n\n        if (selfptr == needle._ptr) {\n            return true;\n        }\n\n        bool equal;\n        assembly {\n            let length := mload(needle)\n            let needleptr := mload(add(needle, 0x20))\n            equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\n        }\n\n        return equal;\n    }\n\n    /*\n     * @dev If `self` ends with `needle`, `needle` is removed from the\n     *      end of `self`. Otherwise, `self` is unmodified.\n     * @param self The slice to operate on.\n     * @param needle The slice to search for.\n     * @return `self`\n     */\n    function until(slice memory self, slice memory needle) internal pure returns (slice memory) {\n        if (self._len < needle._len) {\n            return self;\n        }\n\n        uint selfptr = self._ptr + self._len - needle._len;\n        bool equal = true;\n        if (selfptr != needle._ptr) {\n            assembly {\n                let length := mload(needle)\n                let needleptr := mload(add(needle, 0x20))\n                equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))\n            }\n        }\n\n        if (equal) {\n            self._len -= needle._len;\n        }\n\n        return self;\n    }\n\n    // Returns the memory address of the first byte of the first occurrence of\n    // `needle` in `self`, or the first byte after `self` if not found.\n    function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) {\n        uint ptr = selfptr;\n        uint idx;\n\n        if (needlelen <= selflen) {\n            if (needlelen <= 32) {\n                bytes32 mask;\n                if (needlelen > 0) {\n                    mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1));\n                }\n\n                bytes32 needledata;\n                assembly { needledata := and(mload(needleptr), mask) }\n\n                uint end = selfptr + selflen - needlelen;\n                bytes32 ptrdata;\n                assembly { ptrdata := and(mload(ptr), mask) }\n\n                while (ptrdata != needledata) {\n                    if (ptr >= end)\n                        return selfptr + selflen;\n                    ptr++;\n                    assembly { ptrdata := and(mload(ptr), mask) }\n                }\n                return ptr;\n            } else {\n                // For long needles, use hashing\n                bytes32 hash;\n                assembly { hash := keccak256(needleptr, needlelen) }\n\n                for (idx = 0; idx <= selflen - needlelen; idx++) {\n                    bytes32 testHash;\n                    assembly { testHash := keccak256(ptr, needlelen) }\n                    if (hash == testHash)\n                        return ptr;\n                    ptr += 1;\n                }\n            }\n        }\n        return selfptr + selflen;\n    }\n\n    // Returns the memory address of the first byte after the last occurrence of\n    // `needle` in `self`, or the address of `self` if not found.\n    function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) {\n        uint ptr;\n\n        if (needlelen <= selflen) {\n            if (needlelen <= 32) {\n                bytes32 mask;\n                if (needlelen > 0) {\n                    mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1));\n                }\n\n                bytes32 needledata;\n                assembly { needledata := and(mload(needleptr), mask) }\n\n                ptr = selfptr + selflen - needlelen;\n                bytes32 ptrdata;\n                assembly { ptrdata := and(mload(ptr), mask) }\n\n                while (ptrdata != needledata) {\n                    if (ptr <= selfptr)\n                        return selfptr;\n                    ptr--;\n                    assembly { ptrdata := and(mload(ptr), mask) }\n                }\n                return ptr + needlelen;\n            } else {\n                // For long needles, use hashing\n                bytes32 hash;\n                assembly { hash := keccak256(needleptr, needlelen) }\n                ptr = selfptr + (selflen - needlelen);\n                while (ptr >= selfptr) {\n                    bytes32 testHash;\n                    assembly { testHash := keccak256(ptr, needlelen) }\n                    if (hash == testHash)\n                        return ptr + needlelen;\n                    ptr -= 1;\n                }\n            }\n        }\n        return selfptr;\n    }\n\n    /*\n     * @dev Modifies `self` to contain everything from the first occurrence of\n     *      `needle` to the end of the slice. `self` is set to the empty slice\n     *      if `needle` is not found.\n     * @param self The slice to search and modify.\n     * @param needle The text to search for.\n     * @return `self`.\n     */\n    function find(slice memory self, slice memory needle) internal pure returns (slice memory) {\n        uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr);\n        self._len -= ptr - self._ptr;\n        self._ptr = ptr;\n        return self;\n    }\n\n    /*\n     * @dev Modifies `self` to contain the part of the string from the start of\n     *      `self` to the end of the first occurrence of `needle`. If `needle`\n     *      is not found, `self` is set to the empty slice.\n     * @param self The slice to search and modify.\n     * @param needle The text to search for.\n     * @return `self`.\n     */\n    function rfind(slice memory self, slice memory needle) internal pure returns (slice memory) {\n        uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr);\n        self._len = ptr - self._ptr;\n        return self;\n    }\n\n    /*\n     * @dev Splits the slice, setting `self` to everything after the first\n     *      occurrence of `needle`, and `token` to everything before it. If\n     *      `needle` does not occur in `self`, `self` is set to the empty slice,\n     *      and `token` is set to the entirety of `self`.\n     * @param self The slice to split.\n     * @param needle The text to search for in `self`.\n     * @param token An output parameter to which the first token is written.\n     * @return `token`.\n     */\n    function split(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) {\n        uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr);\n        token._ptr = self._ptr;\n        token._len = ptr - self._ptr;\n        if (ptr == self._ptr + self._len) {\n            // Not found\n            self._len = 0;\n        } else {\n            self._len -= token._len + needle._len;\n            self._ptr = ptr + needle._len;\n        }\n        return token;\n    }\n\n    /*\n     * @dev Splits the slice, setting `self` to everything after the first\n     *      occurrence of `needle`, and returning everything before it. If\n     *      `needle` does not occur in `self`, `self` is set to the empty slice,\n     *      and the entirety of `self` is returned.\n     * @param self The slice to split.\n     * @param needle The text to search for in `self`.\n     * @return The part of `self` up to the first occurrence of `delim`.\n     */\n    function split(slice memory self, slice memory needle) internal pure returns (slice memory token) {\n        split(self, needle, token);\n    }\n\n    /*\n     * @dev Splits the slice, setting `self` to everything before the last\n     *      occurrence of `needle`, and `token` to everything after it. If\n     *      `needle` does not occur in `self`, `self` is set to the empty slice,\n     *      and `token` is set to the entirety of `self`.\n     * @param self The slice to split.\n     * @param needle The text to search for in `self`.\n     * @param token An output parameter to which the first token is written.\n     * @return `token`.\n     */\n    function rsplit(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) {\n        uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr);\n        token._ptr = ptr;\n        token._len = self._len - (ptr - self._ptr);\n        if (ptr == self._ptr) {\n            // Not found\n            self._len = 0;\n        } else {\n            self._len -= token._len + needle._len;\n        }\n        return token;\n    }\n\n    /*\n     * @dev Splits the slice, setting `self` to everything before the last\n     *      occurrence of `needle`, and returning everything after it. If\n     *      `needle` does not occur in `self`, `self` is set to the empty slice,\n     *      and the entirety of `self` is returned.\n     * @param self The slice to split.\n     * @param needle The text to search for in `self`.\n     * @return The part of `self` after the last occurrence of `delim`.\n     */\n    function rsplit(slice memory self, slice memory needle) internal pure returns (slice memory token) {\n        rsplit(self, needle, token);\n    }\n\n    /*\n     * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`.\n     * @param self The slice to search.\n     * @param needle The text to search for in `self`.\n     * @return The number of occurrences of `needle` found in `self`.\n     */\n    function count(slice memory self, slice memory needle) internal pure returns (uint cnt) {\n        uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len;\n        while (ptr <= self._ptr + self._len) {\n            cnt++;\n            ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len;\n        }\n    }\n\n    /*\n     * @dev Returns True if `self` contains `needle`.\n     * @param self The slice to search.\n     * @param needle The text to search for in `self`.\n     * @return True if `needle` is found in `self`, false otherwise.\n     */\n    function contains(slice memory self, slice memory needle) internal pure returns (bool) {\n        return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr;\n    }\n\n    /*\n     * @dev Returns a newly allocated string containing the concatenation of\n     *      `self` and `other`.\n     * @param self The first slice to concatenate.\n     * @param other The second slice to concatenate.\n     * @return The concatenation of the two strings.\n     */\n    function concat(slice memory self, slice memory other) internal pure returns (string memory) {\n        string memory ret = new string(self._len + other._len);\n        uint retptr;\n        assembly { retptr := add(ret, 32) }\n        memcpy(retptr, self._ptr, self._len);\n        memcpy(retptr + self._len, other._ptr, other._len);\n        return ret;\n    }\n\n    /*\n     * @dev Joins an array of slices, using `self` as a delimiter, returning a\n     *      newly allocated string.\n     * @param self The delimiter to use.\n     * @param parts A list of slices to join.\n     * @return A newly allocated string containing all the slices in `parts`,\n     *         joined with `self`.\n     */\n    function join(slice memory self, slice[] memory parts) internal pure returns (string memory) {\n        if (parts.length == 0)\n            return \"\";\n\n        uint length = self._len * (parts.length - 1);\n        for(uint i = 0; i < parts.length; i++)\n            length += parts[i]._len;\n\n        string memory ret = new string(length);\n        uint retptr;\n        assembly { retptr := add(ret, 32) }\n\n        for(uint i = 0; i < parts.length; i++) {\n            memcpy(retptr, parts[i]._ptr, parts[i]._len);\n            retptr += parts[i]._len;\n            if (i < parts.length - 1) {\n                memcpy(retptr, self._ptr, self._len);\n                retptr += self._len;\n            }\n        }\n\n        return ret;\n    }\n}"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 1200
      },
      "viaIR": true,
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      }
    }
  }}