{
  "language": "Solidity",
  "sources": {
    "@ensdomains/buffer/contracts/Buffer.sol": {
      "content": "// SPDX-License-Identifier: BSD-2-Clause\npragma solidity ^0.8.4;\n\n/**\n* @dev A library for working with mutable byte buffers in Solidity.\n*\n* Byte buffers are mutable and expandable, and provide a variety of primitives\n* for appending to them. At any time you can fetch a bytes object containing the\n* current contents of the buffer. The bytes object should not be stored between\n* operations, as it may change due to resizing of the buffer.\n*/\nlibrary Buffer {\n    /**\n    * @dev Represents a mutable buffer. Buffers have a current value (buf) and\n    *      a capacity. The capacity may be longer than the current value, in\n    *      which case it can be extended without the need to allocate more memory.\n    */\n    struct buffer {\n        bytes buf;\n        uint capacity;\n    }\n\n    /**\n    * @dev Initializes a buffer with an initial capacity.\n    * @param buf The buffer to initialize.\n    * @param capacity The number of bytes of space to allocate the buffer.\n    * @return The buffer, for chaining.\n    */\n    function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {\n        if (capacity % 32 != 0) {\n            capacity += 32 - (capacity % 32);\n        }\n        // Allocate space for the buffer data\n        buf.capacity = capacity;\n        assembly {\n            let ptr := mload(0x40)\n            mstore(buf, ptr)\n            mstore(ptr, 0)\n            let fpm := add(32, add(ptr, capacity))\n            if lt(fpm, ptr) {\n                revert(0, 0)\n            }\n            mstore(0x40, fpm)\n        }\n        return buf;\n    }\n\n    /**\n    * @dev Initializes a new buffer from an existing bytes object.\n    *      Changes to the buffer may mutate the original value.\n    * @param b The bytes object to initialize the buffer with.\n    * @return A new buffer.\n    */\n    function fromBytes(bytes memory b) internal pure returns(buffer memory) {\n        buffer memory buf;\n        buf.buf = b;\n        buf.capacity = b.length;\n        return buf;\n    }\n\n    function resize(buffer memory buf, uint capacity) private pure {\n        bytes memory oldbuf = buf.buf;\n        init(buf, capacity);\n        append(buf, oldbuf);\n    }\n\n    /**\n    * @dev Sets buffer length to 0.\n    * @param buf The buffer to truncate.\n    * @return The original buffer, for chaining..\n    */\n    function truncate(buffer memory buf) internal pure returns (buffer memory) {\n        assembly {\n            let bufptr := mload(buf)\n            mstore(bufptr, 0)\n        }\n        return buf;\n    }\n\n    /**\n    * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed\n    *      the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @param len The number of bytes to copy.\n    * @return The original buffer, for chaining.\n    */\n    function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) {\n        require(len <= data.length);\n\n        uint off = buf.buf.length;\n        uint newCapacity = off + len;\n        if (newCapacity > buf.capacity) {\n            resize(buf, newCapacity * 2);\n        }\n\n        uint dest;\n        uint src;\n        assembly {\n            // Memory address of the buffer data\n            let bufptr := mload(buf)\n            // Length of existing buffer data\n            let buflen := mload(bufptr)\n            // Start address = buffer address + offset + sizeof(buffer length)\n            dest := add(add(bufptr, 32), off)\n            // Update buffer length if we're extending it\n            if gt(newCapacity, buflen) {\n                mstore(bufptr, newCapacity)\n            }\n            src := add(data, 32)\n        }\n\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            uint 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        return buf;\n    }\n\n    /**\n    * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\n    *      the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @return The original buffer, for chaining.\n    */\n    function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\n        return append(buf, data, data.length);\n    }\n\n    /**\n    * @dev Appends a byte to the buffer. Resizes if doing so would exceed the\n    *      capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @return The original buffer, for chaining.\n    */\n    function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {\n        uint off = buf.buf.length;\n        uint offPlusOne = off + 1;\n        if (off >= buf.capacity) {\n            resize(buf, offPlusOne * 2);\n        }\n\n        assembly {\n            // Memory address of the buffer data\n            let bufptr := mload(buf)\n            // Address = buffer address + sizeof(buffer length) + off\n            let dest := add(add(bufptr, off), 32)\n            mstore8(dest, data)\n            // Update buffer length if we extended it\n            if gt(offPlusOne, mload(bufptr)) {\n                mstore(bufptr, offPlusOne)\n            }\n        }\n\n        return buf;\n    }\n\n    /**\n    * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would\n    *      exceed the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @param len The number of bytes to write (left-aligned).\n    * @return The original buffer, for chaining.\n    */\n    function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) {\n        uint off = buf.buf.length;\n        uint newCapacity = len + off;\n        if (newCapacity > buf.capacity) {\n            resize(buf, newCapacity * 2);\n        }\n\n        unchecked {\n            uint mask = (256 ** len) - 1;\n            // Right-align data\n            data = data >> (8 * (32 - len));\n            assembly {\n                // Memory address of the buffer data\n                let bufptr := mload(buf)\n                // Address = buffer address + sizeof(buffer length) + newCapacity\n                let dest := add(bufptr, newCapacity)\n                mstore(dest, or(and(mload(dest), not(mask)), data))\n                // Update buffer length if we extended it\n                if gt(newCapacity, mload(bufptr)) {\n                    mstore(bufptr, newCapacity)\n                }\n            }\n        }\n        return buf;\n    }\n\n    /**\n    * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed\n    *      the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @return The original buffer, for chhaining.\n    */\n    function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {\n        return append(buf, bytes32(data), 20);\n    }\n\n    /**\n    * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed\n    *      the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param data The data to append.\n    * @return The original buffer, for chaining.\n    */\n    function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {\n        return append(buf, data, 32);\n    }\n\n    /**\n     * @dev Appends a byte to the end of the buffer. Resizes if doing so would\n     *      exceed the capacity of the buffer.\n     * @param buf The buffer to append to.\n     * @param data The data to append.\n     * @param len The number of bytes to write (right-aligned).\n     * @return The original buffer.\n     */\n    function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {\n        uint off = buf.buf.length;\n        uint newCapacity = len + off;\n        if (newCapacity > buf.capacity) {\n            resize(buf, newCapacity * 2);\n        }\n\n        uint mask = (256 ** len) - 1;\n        assembly {\n            // Memory address of the buffer data\n            let bufptr := mload(buf)\n            // Address = buffer address + sizeof(buffer length) + newCapacity\n            let dest := add(bufptr, newCapacity)\n            mstore(dest, or(and(mload(dest), not(mask)), data))\n            // Update buffer length if we extended it\n            if gt(newCapacity, mload(bufptr)) {\n                mstore(bufptr, newCapacity)\n            }\n        }\n        return buf;\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\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        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _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        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\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 v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/ERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
    },
    "contracts/dnsregistrar/DNSClaimChecker.sol": {
      "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"../dnssec-oracle/DNSSEC.sol\";\nimport \"../dnssec-oracle/BytesUtils.sol\";\nimport \"../dnssec-oracle/RRUtils.sol\";\nimport \"../utils/HexUtils.sol\";\nimport \"@ensdomains/buffer/contracts/Buffer.sol\";\n\nlibrary DNSClaimChecker {\n    using BytesUtils for bytes;\n    using HexUtils for bytes;\n    using RRUtils for *;\n    using Buffer for Buffer.buffer;\n\n    uint16 constant CLASS_INET = 1;\n    uint16 constant TYPE_TXT = 16;\n\n    function getOwnerAddress(\n        bytes memory name,\n        bytes memory data\n    ) internal pure returns (address, bool) {\n        // Add \"_ens.\" to the front of the name.\n        Buffer.buffer memory buf;\n        buf.init(name.length + 5);\n        buf.append(\"\\x04_ens\");\n        buf.append(name);\n\n        for (\n            RRUtils.RRIterator memory iter = data.iterateRRs(0);\n            !iter.done();\n            iter.next()\n        ) {\n            if (iter.name().compareNames(buf.buf) != 0) continue;\n            bool found;\n            address addr;\n            (addr, found) = parseRR(data, iter.rdataOffset, iter.nextOffset);\n            if (found) {\n                return (addr, true);\n            }\n        }\n\n        return (address(0x0), false);\n    }\n\n    function parseRR(\n        bytes memory rdata,\n        uint256 idx,\n        uint256 endIdx\n    ) internal pure returns (address, bool) {\n        while (idx < endIdx) {\n            uint256 len = rdata.readUint8(idx);\n            idx += 1;\n\n            bool found;\n            address addr;\n            (addr, found) = parseString(rdata, idx, len);\n\n            if (found) return (addr, true);\n            idx += len;\n        }\n\n        return (address(0x0), false);\n    }\n\n    function parseString(\n        bytes memory str,\n        uint256 idx,\n        uint256 len\n    ) internal pure returns (address, bool) {\n        // TODO: More robust parsing that handles whitespace and multiple key/value pairs\n        if (str.readUint32(idx) != 0x613d3078) return (address(0x0), false); // 0x613d3078 == 'a=0x'\n        return str.hexToAddress(idx + 4, idx + len);\n    }\n}\n"
    },
    "contracts/dnsregistrar/DNSRegistrar.sol": {
      "content": "//SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.4;\n\nimport \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport \"@ensdomains/buffer/contracts/Buffer.sol\";\nimport \"../dnssec-oracle/BytesUtils.sol\";\nimport \"../dnssec-oracle/DNSSEC.sol\";\nimport \"../dnssec-oracle/RRUtils.sol\";\nimport \"../registry/ENSRegistry.sol\";\nimport \"../root/Root.sol\";\nimport \"../resolvers/profiles/AddrResolver.sol\";\nimport \"./DNSClaimChecker.sol\";\nimport \"./PublicSuffixList.sol\";\nimport \"./IDNSRegistrar.sol\";\n\n/**\n * @dev An ENS registrar that allows the owner of a DNS name to claim the\n *      corresponding name in ENS.\n */\ncontract DNSRegistrar is IDNSRegistrar, IERC165 {\n    using BytesUtils for bytes;\n    using Buffer for Buffer.buffer;\n    using RRUtils for *;\n\n    ENS public immutable ens;\n    DNSSEC public immutable oracle;\n    PublicSuffixList public suffixes;\n    address public immutable previousRegistrar;\n    address public immutable resolver;\n    // A mapping of the most recent signatures seen for each claimed domain.\n    mapping(bytes32 => uint32) public inceptions;\n\n    error NoOwnerRecordFound();\n    error PermissionDenied(address caller, address owner);\n    error PreconditionNotMet();\n    error StaleProof();\n    error InvalidPublicSuffix(bytes name);\n\n    struct OwnerRecord {\n        bytes name;\n        address owner;\n        address resolver;\n        uint64 ttl;\n    }\n\n    event Claim(\n        bytes32 indexed node,\n        address indexed owner,\n        bytes dnsname,\n        uint32 inception\n    );\n    event NewPublicSuffixList(address suffixes);\n\n    constructor(\n        address _previousRegistrar,\n        address _resolver,\n        DNSSEC _dnssec,\n        PublicSuffixList _suffixes,\n        ENS _ens\n    ) {\n        previousRegistrar = _previousRegistrar;\n        resolver = _resolver;\n        oracle = _dnssec;\n        suffixes = _suffixes;\n        emit NewPublicSuffixList(address(suffixes));\n        ens = _ens;\n    }\n\n    /**\n     * @dev This contract's owner-only functions can be invoked by the owner of the ENS root.\n     */\n    modifier onlyOwner() {\n        Root root = Root(ens.owner(bytes32(0)));\n        address owner = root.owner();\n        require(msg.sender == owner);\n        _;\n    }\n\n    function setPublicSuffixList(PublicSuffixList _suffixes) public onlyOwner {\n        suffixes = _suffixes;\n        emit NewPublicSuffixList(address(suffixes));\n    }\n\n    /**\n     * @dev Submits proofs to the DNSSEC oracle, then claims a name using those proofs.\n     * @param name The name to claim, in DNS wire format.\n     * @param input A chain of signed DNS RRSETs ending with a text record.\n     */\n    function proveAndClaim(\n        bytes memory name,\n        DNSSEC.RRSetWithSignature[] memory input\n    ) public override {\n        (bytes32 rootNode, bytes32 labelHash, address addr) = _claim(\n            name,\n            input\n        );\n        ens.setSubnodeOwner(rootNode, labelHash, addr);\n    }\n\n    function proveAndClaimWithResolver(\n        bytes memory name,\n        DNSSEC.RRSetWithSignature[] memory input,\n        address resolver,\n        address addr\n    ) public override {\n        (bytes32 rootNode, bytes32 labelHash, address owner) = _claim(\n            name,\n            input\n        );\n        if (msg.sender != owner) {\n            revert PermissionDenied(msg.sender, owner);\n        }\n        ens.setSubnodeRecord(rootNode, labelHash, owner, resolver, 0);\n        if (addr != address(0)) {\n            if (resolver == address(0)) {\n                revert PreconditionNotMet();\n            }\n            bytes32 node = keccak256(abi.encodePacked(rootNode, labelHash));\n            // Set the resolver record\n            AddrResolver(resolver).setAddr(node, addr);\n        }\n    }\n\n    function supportsInterface(\n        bytes4 interfaceID\n    ) external pure override returns (bool) {\n        return\n            interfaceID == type(IERC165).interfaceId ||\n            interfaceID == type(IDNSRegistrar).interfaceId;\n    }\n\n    function _claim(\n        bytes memory name,\n        DNSSEC.RRSetWithSignature[] memory input\n    ) internal returns (bytes32 parentNode, bytes32 labelHash, address addr) {\n        (bytes memory data, uint32 inception) = oracle.verifyRRSet(input);\n\n        // Get the first label\n        uint256 labelLen = name.readUint8(0);\n        labelHash = name.keccak(1, labelLen);\n\n        bytes memory parentName = name.substring(\n            labelLen + 1,\n            name.length - labelLen - 1\n        );\n\n        // Make sure the parent name is enabled\n        parentNode = enableNode(parentName);\n\n        bytes32 node = keccak256(abi.encodePacked(parentNode, labelHash));\n        if (!RRUtils.serialNumberGte(inception, inceptions[node])) {\n            revert StaleProof();\n        }\n        inceptions[node] = inception;\n\n        bool found;\n        (addr, found) = DNSClaimChecker.getOwnerAddress(name, data);\n        if (!found) {\n            revert NoOwnerRecordFound();\n        }\n\n        emit Claim(node, addr, name, inception);\n    }\n\n    function enableNode(bytes memory domain) public returns (bytes32 node) {\n        // Name must be in the public suffix list.\n        if (!suffixes.isPublicSuffix(domain)) {\n            revert InvalidPublicSuffix(domain);\n        }\n        return _enableNode(domain, 0);\n    }\n\n    function _enableNode(\n        bytes memory domain,\n        uint256 offset\n    ) internal returns (bytes32 node) {\n        uint256 len = domain.readUint8(offset);\n        if (len == 0) {\n            return bytes32(0);\n        }\n\n        bytes32 parentNode = _enableNode(domain, offset + len + 1);\n        bytes32 label = domain.keccak(offset + 1, len);\n        node = keccak256(abi.encodePacked(parentNode, label));\n        address owner = ens.owner(node);\n        if (owner == address(0) || owner == previousRegistrar) {\n            if (parentNode == bytes32(0)) {\n                Root root = Root(ens.owner(bytes32(0)));\n                root.setSubnodeOwner(label, address(this));\n                ens.setResolver(node, resolver);\n            } else {\n                ens.setSubnodeRecord(\n                    parentNode,\n                    label,\n                    address(this),\n                    resolver,\n                    0\n                );\n            }\n        } else if (owner != address(this)) {\n            revert PreconditionNotMet();\n        }\n        return node;\n    }\n}\n"
    },
    "contracts/dnsregistrar/IDNSRegistrar.sol": {
      "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"../dnssec-oracle/DNSSEC.sol\";\n\ninterface IDNSRegistrar {\n    function proveAndClaim(\n        bytes memory name,\n        DNSSEC.RRSetWithSignature[] memory input\n    ) external;\n\n    function proveAndClaimWithResolver(\n        bytes memory name,\n        DNSSEC.RRSetWithSignature[] memory input,\n        address resolver,\n        address addr\n    ) external;\n}\n"
    },
    "contracts/dnsregistrar/mocks/DummyNonCCIPAwareResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport \"../OffchainDNSResolver.sol\";\nimport \"../../resolvers/profiles/IExtendedResolver.sol\";\n\ncontract DummyNonCCIPAwareResolver is IExtendedResolver, ERC165 {\n    OffchainDNSResolver dnsResolver;\n\n    constructor(OffchainDNSResolver _dnsResolver) {\n        dnsResolver = _dnsResolver;\n    }\n\n    function supportsInterface(\n        bytes4 interfaceId\n    ) public view virtual override returns (bool) {\n        return\n            interfaceId == type(IExtendedResolver).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    function resolve(\n        bytes calldata /* name */,\n        bytes calldata data\n    ) external view returns (bytes memory) {\n        string[] memory urls = new string[](1);\n        urls[0] = \"https://example.com/\";\n        revert OffchainLookup(\n            address(dnsResolver),\n            urls,\n            data,\n            OffchainDNSResolver.resolveCallback.selector,\n            data\n        );\n    }\n}\n"
    },
    "contracts/dnsregistrar/mocks/DummyParser.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"../../dnssec-oracle/BytesUtils.sol\";\nimport \"../RecordParser.sol\";\n\ncontract DummyParser {\n    using BytesUtils for bytes;\n\n    // parse data in format: name;key1=value1 key2=value2;url\n    function parseData(\n        bytes memory data,\n        uint256 kvCount\n    )\n        external\n        pure\n        returns (\n            string memory name,\n            string[] memory keys,\n            string[] memory values,\n            string memory url\n        )\n    {\n        uint256 len = data.length;\n        // retrieve name\n        uint256 sep1 = data.find(0, len, \";\");\n        name = string(data.substring(0, sep1));\n\n        // retrieve url\n        uint256 sep2 = data.find(sep1 + 1, len - sep1, \";\");\n        url = string(data.substring(sep2 + 1, len - sep2 - 1));\n\n        keys = new string[](kvCount);\n        values = new string[](kvCount);\n        // retrieve keys and values\n        uint256 offset = sep1 + 1;\n        for (uint256 i; i < kvCount && offset < len; i++) {\n            (\n                bytes memory key,\n                bytes memory val,\n                uint256 nextOffset\n            ) = RecordParser.readKeyValue(data, offset, sep2 - offset);\n            keys[i] = string(key);\n            values[i] = string(val);\n            offset = nextOffset;\n        }\n    }\n}\n"
    },
    "contracts/dnsregistrar/OffchainDNSResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"../../contracts/resolvers/profiles/IAddrResolver.sol\";\nimport \"../../contracts/resolvers/profiles/IExtendedResolver.sol\";\nimport \"../../contracts/resolvers/profiles/IExtendedDNSResolver.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport \"../dnssec-oracle/BytesUtils.sol\";\nimport \"../dnssec-oracle/DNSSEC.sol\";\nimport \"../dnssec-oracle/RRUtils.sol\";\nimport \"../registry/ENSRegistry.sol\";\nimport \"../utils/HexUtils.sol\";\n\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {LowLevelCallUtils} from \"../utils/LowLevelCallUtils.sol\";\n\nerror InvalidOperation();\nerror OffchainLookup(\n    address sender,\n    string[] urls,\n    bytes callData,\n    bytes4 callbackFunction,\n    bytes extraData\n);\n\ninterface IDNSGateway {\n    function resolve(\n        bytes memory name,\n        uint16 qtype\n    ) external returns (DNSSEC.RRSetWithSignature[] memory);\n}\n\nuint16 constant CLASS_INET = 1;\nuint16 constant TYPE_TXT = 16;\n\ncontract OffchainDNSResolver is IExtendedResolver {\n    using RRUtils for *;\n    using Address for address;\n    using BytesUtils for bytes;\n    using HexUtils for bytes;\n\n    ENS public immutable ens;\n    DNSSEC public immutable oracle;\n    string public gatewayURL;\n\n    error CouldNotResolve(bytes name);\n\n    constructor(ENS _ens, DNSSEC _oracle, string memory _gatewayURL) {\n        ens = _ens;\n        oracle = _oracle;\n        gatewayURL = _gatewayURL;\n    }\n\n    function resolve(\n        bytes calldata name,\n        bytes calldata data\n    ) external view returns (bytes memory) {\n        return\n            callWithOffchainLookupPropagation(\n                msg.sender,\n                name,\n                data,\n                abi.encodeCall(IExtendedResolver.resolve, (name, data))\n            );\n    }\n\n    function resolveCallback(\n        bytes calldata response,\n        bytes calldata extraData\n    ) external view returns (bytes memory) {\n        (bytes memory name, bytes memory query) = abi.decode(\n            extraData,\n            (bytes, bytes)\n        );\n        DNSSEC.RRSetWithSignature[] memory rrsets = abi.decode(\n            response,\n            (DNSSEC.RRSetWithSignature[])\n        );\n\n        (bytes memory data, ) = oracle.verifyRRSet(rrsets);\n        for (\n            RRUtils.RRIterator memory iter = data.iterateRRs(0);\n            !iter.done();\n            iter.next()\n        ) {\n            // Ignore records with wrong name, type, or class\n            bytes memory rrname = RRUtils.readName(iter.data, iter.offset);\n            if (\n                !rrname.equals(name) ||\n                iter.class != CLASS_INET ||\n                iter.dnstype != TYPE_TXT\n            ) {\n                continue;\n            }\n\n            // Look for a valid ENS-DNS TXT record\n            (address dnsresolver, bytes memory context) = parseRR(\n                iter.data,\n                iter.rdataOffset,\n                iter.nextOffset\n            );\n\n            // If we found a valid record, try to resolve it\n            if (dnsresolver != address(0)) {\n                if (\n                    IERC165(dnsresolver).supportsInterface(\n                        IExtendedDNSResolver.resolve.selector\n                    )\n                ) {\n                    return\n                        callWithOffchainLookupPropagation(\n                            dnsresolver,\n                            name,\n                            query,\n                            abi.encodeCall(\n                                IExtendedDNSResolver.resolve,\n                                (name, query, context)\n                            )\n                        );\n                } else if (\n                    IERC165(dnsresolver).supportsInterface(\n                        IExtendedResolver.resolve.selector\n                    )\n                ) {\n                    return\n                        callWithOffchainLookupPropagation(\n                            dnsresolver,\n                            name,\n                            query,\n                            abi.encodeCall(\n                                IExtendedResolver.resolve,\n                                (name, query)\n                            )\n                        );\n                } else {\n                    (bool ok, bytes memory ret) = address(dnsresolver)\n                        .staticcall(query);\n                    if (ok) {\n                        return ret;\n                    } else {\n                        revert CouldNotResolve(name);\n                    }\n                }\n            }\n        }\n\n        // No valid records; revert.\n        revert CouldNotResolve(name);\n    }\n\n    function parseRR(\n        bytes memory data,\n        uint256 idx,\n        uint256 lastIdx\n    ) internal view returns (address, bytes memory) {\n        bytes memory txt = readTXT(data, idx, lastIdx);\n\n        // Must start with the magic word\n        if (txt.length < 5 || !txt.equals(0, \"ENS1 \", 0, 5)) {\n            return (address(0), \"\");\n        }\n\n        // Parse the name or address\n        uint256 lastTxtIdx = txt.find(5, txt.length - 5, \" \");\n        if (lastTxtIdx > txt.length) {\n            address dnsResolver = parseAndResolve(txt, 5, txt.length);\n            return (dnsResolver, \"\");\n        } else {\n            address dnsResolver = parseAndResolve(txt, 5, lastTxtIdx);\n            return (\n                dnsResolver,\n                txt.substring(lastTxtIdx + 1, txt.length - lastTxtIdx - 1)\n            );\n        }\n    }\n\n    function readTXT(\n        bytes memory data,\n        uint256 startIdx,\n        uint256 lastIdx\n    ) internal pure returns (bytes memory) {\n        // TODO: Concatenate multiple text fields\n        uint256 fieldLength = data.readUint8(startIdx);\n        assert(startIdx + fieldLength < lastIdx);\n        return data.substring(startIdx + 1, fieldLength);\n    }\n\n    function parseAndResolve(\n        bytes memory nameOrAddress,\n        uint256 idx,\n        uint256 lastIdx\n    ) internal view returns (address) {\n        if (nameOrAddress[idx] == \"0\" && nameOrAddress[idx + 1] == \"x\") {\n            (address ret, bool valid) = nameOrAddress.hexToAddress(\n                idx + 2,\n                lastIdx\n            );\n            if (valid) {\n                return ret;\n            }\n        }\n        return resolveName(nameOrAddress, idx, lastIdx);\n    }\n\n    function resolveName(\n        bytes memory name,\n        uint256 idx,\n        uint256 lastIdx\n    ) internal view returns (address) {\n        bytes32 node = textNamehash(name, idx, lastIdx);\n        address resolver = ens.resolver(node);\n        if (resolver == address(0)) {\n            return address(0);\n        }\n        return IAddrResolver(resolver).addr(node);\n    }\n\n    /**\n     * @dev Namehash function that operates on dot-separated names (not dns-encoded names)\n     * @param name Name to hash\n     * @param idx Index to start at\n     * @param lastIdx Index to end at\n     */\n    function textNamehash(\n        bytes memory name,\n        uint256 idx,\n        uint256 lastIdx\n    ) internal view returns (bytes32) {\n        uint256 separator = name.find(idx, name.length - idx, bytes1(\".\"));\n        bytes32 parentNode = bytes32(0);\n        if (separator < lastIdx) {\n            parentNode = textNamehash(name, separator + 1, lastIdx);\n        } else {\n            separator = lastIdx;\n        }\n        return\n            keccak256(\n                abi.encodePacked(parentNode, name.keccak(idx, separator - idx))\n            );\n    }\n\n    function callWithOffchainLookupPropagation(\n        address target,\n        bytes memory name,\n        bytes memory innerdata,\n        bytes memory data\n    ) internal view returns (bytes memory) {\n        if (target.isContract()) {\n            bool result = LowLevelCallUtils.functionStaticCall(\n                address(target),\n                data\n            );\n            uint256 size = LowLevelCallUtils.returnDataSize();\n            if (result) {\n                bytes memory returnData = LowLevelCallUtils.readReturnData(\n                    0,\n                    size\n                );\n                return abi.decode(returnData, (bytes));\n            }\n            // Failure\n            if (size >= 4) {\n                bytes memory errorId = LowLevelCallUtils.readReturnData(0, 4);\n                if (bytes4(errorId) == OffchainLookup.selector) {\n                    // Offchain lookup. Decode the revert message and create our own that nests it.\n                    bytes memory revertData = LowLevelCallUtils.readReturnData(\n                        4,\n                        size - 4\n                    );\n                    (\n                        address sender,\n                        string[] memory urls,\n                        bytes memory callData,\n                        bytes4 innerCallbackFunction,\n                        bytes memory extraData\n                    ) = abi.decode(\n                            revertData,\n                            (address, string[], bytes, bytes4, bytes)\n                        );\n\n                    if (sender != target) {\n                        revert InvalidOperation();\n                    }\n\n                    revert OffchainLookup(\n                        address(this),\n                        urls,\n                        callData,\n                        OffchainDNSResolver.resolveCallback.selector,\n                        abi.encode(sender, innerCallbackFunction, extraData)\n                    );\n                }\n            }\n            LowLevelCallUtils.propagateRevert();\n        } else {\n            string[] memory urls = new string[](1);\n            urls[0] = gatewayURL;\n\n            revert OffchainLookup(\n                address(this),\n                urls,\n                abi.encodeCall(IDNSGateway.resolve, (name, TYPE_TXT)),\n                OffchainDNSResolver.resolveCallback.selector,\n                abi.encode(name, innerdata)\n            );\n        }\n    }\n}\n"
    },
    "contracts/dnsregistrar/PublicSuffixList.sol": {
      "content": "pragma solidity ^0.8.4;\n\ninterface PublicSuffixList {\n    function isPublicSuffix(bytes calldata name) external view returns (bool);\n}\n"
    },
    "contracts/dnsregistrar/RecordParser.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.11;\n\nimport \"../dnssec-oracle/BytesUtils.sol\";\n\nlibrary RecordParser {\n    using BytesUtils for bytes;\n\n    /**\n     * @dev Parses a key-value record into a key and value.\n     * @param input The input string\n     * @param offset The offset to start reading at\n     */\n    function readKeyValue(\n        bytes memory input,\n        uint256 offset,\n        uint256 len\n    )\n        internal\n        pure\n        returns (bytes memory key, bytes memory value, uint256 nextOffset)\n    {\n        uint256 separator = input.find(offset, len, \"=\");\n        if (separator == type(uint256).max) {\n            return (\"\", \"\", type(uint256).max);\n        }\n\n        uint256 terminator = input.find(\n            separator,\n            len + offset - separator,\n            \" \"\n        );\n        if (terminator == type(uint256).max) {\n            terminator = len + offset;\n            nextOffset = terminator;\n        } else {\n            nextOffset = terminator + 1;\n        }\n\n        key = input.substring(offset, separator - offset);\n        value = input.substring(separator + 1, terminator - separator - 1);\n    }\n}\n"
    },
    "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"
    },
    "contracts/dnssec-oracle/DNSSEC.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\npragma experimental ABIEncoderV2;\n\nabstract contract DNSSEC {\n    bytes public anchors;\n\n    struct RRSetWithSignature {\n        bytes rrset;\n        bytes sig;\n    }\n\n    event AlgorithmUpdated(uint8 id, address addr);\n    event DigestUpdated(uint8 id, address addr);\n\n    function verifyRRSet(\n        RRSetWithSignature[] memory input\n    ) external view virtual returns (bytes memory rrs, uint32 inception);\n\n    function verifyRRSet(\n        RRSetWithSignature[] memory input,\n        uint256 now\n    ) public view virtual returns (bytes memory rrs, uint32 inception);\n}\n"
    },
    "contracts/dnssec-oracle/RRUtils.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"./BytesUtils.sol\";\nimport \"@ensdomains/buffer/contracts/Buffer.sol\";\n\n/**\n * @dev RRUtils is a library that provides utilities for parsing DNS resource records.\n */\nlibrary RRUtils {\n    using BytesUtils for *;\n    using Buffer for *;\n\n    /**\n     * @dev Returns the number of bytes in the DNS name at 'offset' in 'self'.\n     * @param self The byte array to read a name from.\n     * @param offset The offset to start reading at.\n     * @return The length of the DNS name at 'offset', in bytes.\n     */\n    function nameLength(\n        bytes memory self,\n        uint256 offset\n    ) internal pure returns (uint256) {\n        uint256 idx = offset;\n        while (true) {\n            assert(idx < self.length);\n            uint256 labelLen = self.readUint8(idx);\n            idx += labelLen + 1;\n            if (labelLen == 0) {\n                break;\n            }\n        }\n        return idx - offset;\n    }\n\n    /**\n     * @dev Returns a DNS format name at the specified offset of self.\n     * @param self The byte array to read a name from.\n     * @param offset The offset to start reading at.\n     * @return ret The name.\n     */\n    function readName(\n        bytes memory self,\n        uint256 offset\n    ) internal pure returns (bytes memory ret) {\n        uint256 len = nameLength(self, offset);\n        return self.substring(offset, len);\n    }\n\n    /**\n     * @dev Returns the number of labels in the DNS name at 'offset' in 'self'.\n     * @param self The byte array to read a name from.\n     * @param offset The offset to start reading at.\n     * @return The number of labels in the DNS name at 'offset', in bytes.\n     */\n    function labelCount(\n        bytes memory self,\n        uint256 offset\n    ) internal pure returns (uint256) {\n        uint256 count = 0;\n        while (true) {\n            assert(offset < self.length);\n            uint256 labelLen = self.readUint8(offset);\n            offset += labelLen + 1;\n            if (labelLen == 0) {\n                break;\n            }\n            count += 1;\n        }\n        return count;\n    }\n\n    uint256 constant RRSIG_TYPE = 0;\n    uint256 constant RRSIG_ALGORITHM = 2;\n    uint256 constant RRSIG_LABELS = 3;\n    uint256 constant RRSIG_TTL = 4;\n    uint256 constant RRSIG_EXPIRATION = 8;\n    uint256 constant RRSIG_INCEPTION = 12;\n    uint256 constant RRSIG_KEY_TAG = 16;\n    uint256 constant RRSIG_SIGNER_NAME = 18;\n\n    struct SignedSet {\n        uint16 typeCovered;\n        uint8 algorithm;\n        uint8 labels;\n        uint32 ttl;\n        uint32 expiration;\n        uint32 inception;\n        uint16 keytag;\n        bytes signerName;\n        bytes data;\n        bytes name;\n    }\n\n    function readSignedSet(\n        bytes memory data\n    ) internal pure returns (SignedSet memory self) {\n        self.typeCovered = data.readUint16(RRSIG_TYPE);\n        self.algorithm = data.readUint8(RRSIG_ALGORITHM);\n        self.labels = data.readUint8(RRSIG_LABELS);\n        self.ttl = data.readUint32(RRSIG_TTL);\n        self.expiration = data.readUint32(RRSIG_EXPIRATION);\n        self.inception = data.readUint32(RRSIG_INCEPTION);\n        self.keytag = data.readUint16(RRSIG_KEY_TAG);\n        self.signerName = readName(data, RRSIG_SIGNER_NAME);\n        self.data = data.substring(\n            RRSIG_SIGNER_NAME + self.signerName.length,\n            data.length - RRSIG_SIGNER_NAME - self.signerName.length\n        );\n    }\n\n    function rrs(\n        SignedSet memory rrset\n    ) internal pure returns (RRIterator memory) {\n        return iterateRRs(rrset.data, 0);\n    }\n\n    /**\n     * @dev An iterator over resource records.\n     */\n    struct RRIterator {\n        bytes data;\n        uint256 offset;\n        uint16 dnstype;\n        uint16 class;\n        uint32 ttl;\n        uint256 rdataOffset;\n        uint256 nextOffset;\n    }\n\n    /**\n     * @dev Begins iterating over resource records.\n     * @param self The byte string to read from.\n     * @param offset The offset to start reading at.\n     * @return ret An iterator object.\n     */\n    function iterateRRs(\n        bytes memory self,\n        uint256 offset\n    ) internal pure returns (RRIterator memory ret) {\n        ret.data = self;\n        ret.nextOffset = offset;\n        next(ret);\n    }\n\n    /**\n     * @dev Returns true iff there are more RRs to iterate.\n     * @param iter The iterator to check.\n     * @return True iff the iterator has finished.\n     */\n    function done(RRIterator memory iter) internal pure returns (bool) {\n        return iter.offset >= iter.data.length;\n    }\n\n    /**\n     * @dev Moves the iterator to the next resource record.\n     * @param iter The iterator to advance.\n     */\n    function next(RRIterator memory iter) internal pure {\n        iter.offset = iter.nextOffset;\n        if (iter.offset >= iter.data.length) {\n            return;\n        }\n\n        // Skip the name\n        uint256 off = iter.offset + nameLength(iter.data, iter.offset);\n\n        // Read type, class, and ttl\n        iter.dnstype = iter.data.readUint16(off);\n        off += 2;\n        iter.class = iter.data.readUint16(off);\n        off += 2;\n        iter.ttl = iter.data.readUint32(off);\n        off += 4;\n\n        // Read the rdata\n        uint256 rdataLength = iter.data.readUint16(off);\n        off += 2;\n        iter.rdataOffset = off;\n        iter.nextOffset = off + rdataLength;\n    }\n\n    /**\n     * @dev Returns the name of the current record.\n     * @param iter The iterator.\n     * @return A new bytes object containing the owner name from the RR.\n     */\n    function name(RRIterator memory iter) internal pure returns (bytes memory) {\n        return\n            iter.data.substring(\n                iter.offset,\n                nameLength(iter.data, iter.offset)\n            );\n    }\n\n    /**\n     * @dev Returns the rdata portion of the current record.\n     * @param iter The iterator.\n     * @return A new bytes object containing the RR's RDATA.\n     */\n    function rdata(\n        RRIterator memory iter\n    ) internal pure returns (bytes memory) {\n        return\n            iter.data.substring(\n                iter.rdataOffset,\n                iter.nextOffset - iter.rdataOffset\n            );\n    }\n\n    uint256 constant DNSKEY_FLAGS = 0;\n    uint256 constant DNSKEY_PROTOCOL = 2;\n    uint256 constant DNSKEY_ALGORITHM = 3;\n    uint256 constant DNSKEY_PUBKEY = 4;\n\n    struct DNSKEY {\n        uint16 flags;\n        uint8 protocol;\n        uint8 algorithm;\n        bytes publicKey;\n    }\n\n    function readDNSKEY(\n        bytes memory data,\n        uint256 offset,\n        uint256 length\n    ) internal pure returns (DNSKEY memory self) {\n        self.flags = data.readUint16(offset + DNSKEY_FLAGS);\n        self.protocol = data.readUint8(offset + DNSKEY_PROTOCOL);\n        self.algorithm = data.readUint8(offset + DNSKEY_ALGORITHM);\n        self.publicKey = data.substring(\n            offset + DNSKEY_PUBKEY,\n            length - DNSKEY_PUBKEY\n        );\n    }\n\n    uint256 constant DS_KEY_TAG = 0;\n    uint256 constant DS_ALGORITHM = 2;\n    uint256 constant DS_DIGEST_TYPE = 3;\n    uint256 constant DS_DIGEST = 4;\n\n    struct DS {\n        uint16 keytag;\n        uint8 algorithm;\n        uint8 digestType;\n        bytes digest;\n    }\n\n    function readDS(\n        bytes memory data,\n        uint256 offset,\n        uint256 length\n    ) internal pure returns (DS memory self) {\n        self.keytag = data.readUint16(offset + DS_KEY_TAG);\n        self.algorithm = data.readUint8(offset + DS_ALGORITHM);\n        self.digestType = data.readUint8(offset + DS_DIGEST_TYPE);\n        self.digest = data.substring(offset + DS_DIGEST, length - DS_DIGEST);\n    }\n\n    function isSubdomainOf(\n        bytes memory self,\n        bytes memory other\n    ) internal pure returns (bool) {\n        uint256 off = 0;\n        uint256 counts = labelCount(self, 0);\n        uint256 othercounts = labelCount(other, 0);\n\n        while (counts > othercounts) {\n            off = progress(self, off);\n            counts--;\n        }\n\n        return self.equals(off, other, 0);\n    }\n\n    function compareNames(\n        bytes memory self,\n        bytes memory other\n    ) internal pure returns (int256) {\n        if (self.equals(other)) {\n            return 0;\n        }\n\n        uint256 off;\n        uint256 otheroff;\n        uint256 prevoff;\n        uint256 otherprevoff;\n        uint256 counts = labelCount(self, 0);\n        uint256 othercounts = labelCount(other, 0);\n\n        // Keep removing labels from the front of the name until both names are equal length\n        while (counts > othercounts) {\n            prevoff = off;\n            off = progress(self, off);\n            counts--;\n        }\n\n        while (othercounts > counts) {\n            otherprevoff = otheroff;\n            otheroff = progress(other, otheroff);\n            othercounts--;\n        }\n\n        // Compare the last nonequal labels to each other\n        while (counts > 0 && !self.equals(off, other, otheroff)) {\n            prevoff = off;\n            off = progress(self, off);\n            otherprevoff = otheroff;\n            otheroff = progress(other, otheroff);\n            counts -= 1;\n        }\n\n        if (off == 0) {\n            return -1;\n        }\n        if (otheroff == 0) {\n            return 1;\n        }\n\n        return\n            self.compare(\n                prevoff + 1,\n                self.readUint8(prevoff),\n                other,\n                otherprevoff + 1,\n                other.readUint8(otherprevoff)\n            );\n    }\n\n    /**\n     * @dev Compares two serial numbers using RFC1982 serial number math.\n     */\n    function serialNumberGte(\n        uint32 i1,\n        uint32 i2\n    ) internal pure returns (bool) {\n        unchecked {\n            return int32(i1) - int32(i2) >= 0;\n        }\n    }\n\n    function progress(\n        bytes memory body,\n        uint256 off\n    ) internal pure returns (uint256) {\n        return off + 1 + body.readUint8(off);\n    }\n\n    /**\n     * @dev Computes the keytag for a chunk of data.\n     * @param data The data to compute a keytag for.\n     * @return The computed key tag.\n     */\n    function computeKeytag(bytes memory data) internal pure returns (uint16) {\n        /* This function probably deserves some explanation.\n         * The DNSSEC keytag function is a checksum that relies on summing up individual bytes\n         * from the input string, with some mild bitshifting. Here's a Naive solidity implementation:\n         *\n         *     function computeKeytag(bytes memory data) internal pure returns (uint16) {\n         *         uint ac;\n         *         for (uint i = 0; i < data.length; i++) {\n         *             ac += i & 1 == 0 ? uint16(data.readUint8(i)) << 8 : data.readUint8(i);\n         *         }\n         *         return uint16(ac + (ac >> 16));\n         *     }\n         *\n         * The EVM, with its 256 bit words, is exceedingly inefficient at doing byte-by-byte operations;\n         * the code above, on reasonable length inputs, consumes over 100k gas. But we can make the EVM's\n         * large words work in our favour.\n         *\n         * The code below works by treating the input as a series of 256 bit words. It first masks out\n         * even and odd bytes from each input word, adding them to two separate accumulators `ac1` and `ac2`.\n         * The bytes are separated by empty bytes, so as long as no individual sum exceeds 2^16-1, we're\n         * effectively summing 16 different numbers with each EVM ADD opcode.\n         *\n         * Once it's added up all the inputs, it has to add all the 16 bit values in `ac1` and `ac2` together.\n         * It does this using the same trick - mask out every other value, shift to align them, add them together.\n         * After the first addition on both accumulators, there's enough room to add the two accumulators together,\n         * and the remaining sums can be done just on ac1.\n         */\n        unchecked {\n            require(data.length <= 8192, \"Long keys not permitted\");\n            uint256 ac1;\n            uint256 ac2;\n            for (uint256 i = 0; i < data.length + 31; i += 32) {\n                uint256 word;\n                assembly {\n                    word := mload(add(add(data, 32), i))\n                }\n                if (i + 32 > data.length) {\n                    uint256 unused = 256 - (data.length - i) * 8;\n                    word = (word >> unused) << unused;\n                }\n                ac1 +=\n                    (word &\n                        0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >>\n                    8;\n                ac2 += (word &\n                    0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF);\n            }\n            ac1 =\n                (ac1 &\n                    0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\n                ((ac1 &\n                    0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\n                    16);\n            ac2 =\n                (ac2 &\n                    0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\n                ((ac2 &\n                    0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\n                    16);\n            ac1 = (ac1 << 8) + ac2;\n            ac1 =\n                (ac1 &\n                    0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) +\n                ((ac1 &\n                    0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >>\n                    32);\n            ac1 =\n                (ac1 &\n                    0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) +\n                ((ac1 &\n                    0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >>\n                    64);\n            ac1 =\n                (ac1 &\n                    0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +\n                (ac1 >> 128);\n            ac1 += (ac1 >> 16) & 0xFFFF;\n            return uint16(ac1);\n        }\n    }\n}\n"
    },
    "contracts/registry/ENS.sol": {
      "content": "pragma solidity >=0.8.4;\n\ninterface ENS {\n    // Logged when the owner of a node assigns a new owner to a subnode.\n    event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\n\n    // Logged when the owner of a node transfers ownership to a new account.\n    event Transfer(bytes32 indexed node, address owner);\n\n    // Logged when the resolver for a node changes.\n    event NewResolver(bytes32 indexed node, address resolver);\n\n    // Logged when the TTL of a node changes\n    event NewTTL(bytes32 indexed node, uint64 ttl);\n\n    // Logged when an operator is added or removed.\n    event ApprovalForAll(\n        address indexed owner,\n        address indexed operator,\n        bool approved\n    );\n\n    function setRecord(\n        bytes32 node,\n        address owner,\n        address resolver,\n        uint64 ttl\n    ) external;\n\n    function setSubnodeRecord(\n        bytes32 node,\n        bytes32 label,\n        address owner,\n        address resolver,\n        uint64 ttl\n    ) external;\n\n    function setSubnodeOwner(\n        bytes32 node,\n        bytes32 label,\n        address owner\n    ) external returns (bytes32);\n\n    function setResolver(bytes32 node, address resolver) external;\n\n    function setOwner(bytes32 node, address owner) external;\n\n    function setTTL(bytes32 node, uint64 ttl) external;\n\n    function setApprovalForAll(address operator, bool approved) external;\n\n    function owner(bytes32 node) external view returns (address);\n\n    function resolver(bytes32 node) external view returns (address);\n\n    function ttl(bytes32 node) external view returns (uint64);\n\n    function recordExists(bytes32 node) external view returns (bool);\n\n    function isApprovedForAll(\n        address owner,\n        address operator\n    ) external view returns (bool);\n}\n"
    },
    "contracts/registry/ENSRegistry.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"./ENS.sol\";\n\n/**\n * The ENS registry contract.\n */\ncontract ENSRegistry is ENS {\n    struct Record {\n        address owner;\n        address resolver;\n        uint64 ttl;\n    }\n\n    mapping(bytes32 => Record) records;\n    mapping(address => mapping(address => bool)) operators;\n\n    // Permits modifications only by the owner of the specified node.\n    modifier authorised(bytes32 node) {\n        address owner = records[node].owner;\n        require(owner == msg.sender || operators[owner][msg.sender]);\n        _;\n    }\n\n    /**\n     * @dev Constructs a new ENS registry.\n     */\n    constructor() public {\n        records[0x0].owner = msg.sender;\n    }\n\n    /**\n     * @dev Sets the record for a node.\n     * @param node The node to update.\n     * @param owner The address of the new owner.\n     * @param resolver The address of the resolver.\n     * @param ttl The TTL in seconds.\n     */\n    function setRecord(\n        bytes32 node,\n        address owner,\n        address resolver,\n        uint64 ttl\n    ) external virtual override {\n        setOwner(node, owner);\n        _setResolverAndTTL(node, resolver, ttl);\n    }\n\n    /**\n     * @dev Sets the record for a subnode.\n     * @param node The parent node.\n     * @param label The hash of the label specifying the subnode.\n     * @param owner The address of the new owner.\n     * @param resolver The address of the resolver.\n     * @param ttl The TTL in seconds.\n     */\n    function setSubnodeRecord(\n        bytes32 node,\n        bytes32 label,\n        address owner,\n        address resolver,\n        uint64 ttl\n    ) external virtual override {\n        bytes32 subnode = setSubnodeOwner(node, label, owner);\n        _setResolverAndTTL(subnode, resolver, ttl);\n    }\n\n    /**\n     * @dev Transfers ownership of a node to a new address. May only be called by the current owner of the node.\n     * @param node The node to transfer ownership of.\n     * @param owner The address of the new owner.\n     */\n    function setOwner(\n        bytes32 node,\n        address owner\n    ) public virtual override authorised(node) {\n        _setOwner(node, owner);\n        emit Transfer(node, owner);\n    }\n\n    /**\n     * @dev Transfers ownership of a subnode keccak256(node, label) to a new address. May only be called by the owner of the parent node.\n     * @param node The parent node.\n     * @param label The hash of the label specifying the subnode.\n     * @param owner The address of the new owner.\n     */\n    function setSubnodeOwner(\n        bytes32 node,\n        bytes32 label,\n        address owner\n    ) public virtual override authorised(node) returns (bytes32) {\n        bytes32 subnode = keccak256(abi.encodePacked(node, label));\n        _setOwner(subnode, owner);\n        emit NewOwner(node, label, owner);\n        return subnode;\n    }\n\n    /**\n     * @dev Sets the resolver address for the specified node.\n     * @param node The node to update.\n     * @param resolver The address of the resolver.\n     */\n    function setResolver(\n        bytes32 node,\n        address resolver\n    ) public virtual override authorised(node) {\n        emit NewResolver(node, resolver);\n        records[node].resolver = resolver;\n    }\n\n    /**\n     * @dev Sets the TTL for the specified node.\n     * @param node The node to update.\n     * @param ttl The TTL in seconds.\n     */\n    function setTTL(\n        bytes32 node,\n        uint64 ttl\n    ) public virtual override authorised(node) {\n        emit NewTTL(node, ttl);\n        records[node].ttl = ttl;\n    }\n\n    /**\n     * @dev Enable or disable approval for a third party (\"operator\") to manage\n     *  all of `msg.sender`'s ENS records. Emits the ApprovalForAll event.\n     * @param operator Address to add to the set of authorized operators.\n     * @param approved True if the operator is approved, false to revoke approval.\n     */\n    function setApprovalForAll(\n        address operator,\n        bool approved\n    ) external virtual override {\n        operators[msg.sender][operator] = approved;\n        emit ApprovalForAll(msg.sender, operator, approved);\n    }\n\n    /**\n     * @dev Returns the address that owns the specified node.\n     * @param node The specified node.\n     * @return address of the owner.\n     */\n    function owner(\n        bytes32 node\n    ) public view virtual override returns (address) {\n        address addr = records[node].owner;\n        if (addr == address(this)) {\n            return address(0x0);\n        }\n\n        return addr;\n    }\n\n    /**\n     * @dev Returns the address of the resolver for the specified node.\n     * @param node The specified node.\n     * @return address of the resolver.\n     */\n    function resolver(\n        bytes32 node\n    ) public view virtual override returns (address) {\n        return records[node].resolver;\n    }\n\n    /**\n     * @dev Returns the TTL of a node, and any records associated with it.\n     * @param node The specified node.\n     * @return ttl of the node.\n     */\n    function ttl(bytes32 node) public view virtual override returns (uint64) {\n        return records[node].ttl;\n    }\n\n    /**\n     * @dev Returns whether a record has been imported to the registry.\n     * @param node The specified node.\n     * @return Bool if record exists\n     */\n    function recordExists(\n        bytes32 node\n    ) public view virtual override returns (bool) {\n        return records[node].owner != address(0x0);\n    }\n\n    /**\n     * @dev Query if an address is an authorized operator for another address.\n     * @param owner The address that owns the records.\n     * @param operator The address that acts on behalf of the owner.\n     * @return True if `operator` is an approved operator for `owner`, false otherwise.\n     */\n    function isApprovedForAll(\n        address owner,\n        address operator\n    ) external view virtual override returns (bool) {\n        return operators[owner][operator];\n    }\n\n    function _setOwner(bytes32 node, address owner) internal virtual {\n        records[node].owner = owner;\n    }\n\n    function _setResolverAndTTL(\n        bytes32 node,\n        address resolver,\n        uint64 ttl\n    ) internal {\n        if (resolver != records[node].resolver) {\n            records[node].resolver = resolver;\n            emit NewResolver(node, resolver);\n        }\n\n        if (ttl != records[node].ttl) {\n            records[node].ttl = ttl;\n            emit NewTTL(node, ttl);\n        }\n    }\n}\n"
    },
    "contracts/resolvers/profiles/AddrResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\nimport \"../ResolverBase.sol\";\nimport \"./IAddrResolver.sol\";\nimport \"./IAddressResolver.sol\";\n\nabstract contract AddrResolver is\n    IAddrResolver,\n    IAddressResolver,\n    ResolverBase\n{\n    uint256 private constant COIN_TYPE_ETH = 60;\n\n    mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_addresses;\n\n    /**\n     * Sets the address associated with an ENS node.\n     * May only be called by the owner of that node in the ENS registry.\n     * @param node The node to update.\n     * @param a The address to set.\n     */\n    function setAddr(\n        bytes32 node,\n        address a\n    ) external virtual authorised(node) {\n        setAddr(node, COIN_TYPE_ETH, addressToBytes(a));\n    }\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(\n        bytes32 node\n    ) public view virtual override returns (address payable) {\n        bytes memory a = addr(node, COIN_TYPE_ETH);\n        if (a.length == 0) {\n            return payable(0);\n        }\n        return bytesToAddress(a);\n    }\n\n    function setAddr(\n        bytes32 node,\n        uint256 coinType,\n        bytes memory a\n    ) public virtual authorised(node) {\n        emit AddressChanged(node, coinType, a);\n        if (coinType == COIN_TYPE_ETH) {\n            emit AddrChanged(node, bytesToAddress(a));\n        }\n        versionable_addresses[recordVersions[node]][node][coinType] = a;\n    }\n\n    function addr(\n        bytes32 node,\n        uint256 coinType\n    ) public view virtual override returns (bytes memory) {\n        return versionable_addresses[recordVersions[node]][node][coinType];\n    }\n\n    function supportsInterface(\n        bytes4 interfaceID\n    ) public view virtual override returns (bool) {\n        return\n            interfaceID == type(IAddrResolver).interfaceId ||\n            interfaceID == type(IAddressResolver).interfaceId ||\n            super.supportsInterface(interfaceID);\n    }\n\n    function bytesToAddress(\n        bytes memory b\n    ) internal pure returns (address payable a) {\n        require(b.length == 20);\n        assembly {\n            a := div(mload(add(b, 32)), exp(256, 12))\n        }\n    }\n\n    function addressToBytes(address a) internal pure returns (bytes memory b) {\n        b = new bytes(20);\n        assembly {\n            mstore(add(b, 32), mul(a, exp(256, 12)))\n        }\n    }\n}\n"
    },
    "contracts/resolvers/profiles/ExtendedDNSResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport \"../../resolvers/profiles/IExtendedDNSResolver.sol\";\nimport \"../../resolvers/profiles/IAddressResolver.sol\";\nimport \"../../resolvers/profiles/IAddrResolver.sol\";\nimport \"../../utils/HexUtils.sol\";\n\ncontract ExtendedDNSResolver is IExtendedDNSResolver, IERC165 {\n    using HexUtils for *;\n\n    uint256 private constant COIN_TYPE_ETH = 60;\n\n    error NotImplemented();\n    error InvalidAddressFormat();\n\n    function supportsInterface(\n        bytes4 interfaceId\n    ) external view virtual override returns (bool) {\n        return interfaceId == type(IExtendedDNSResolver).interfaceId;\n    }\n\n    function resolve(\n        bytes calldata /* name */,\n        bytes calldata data,\n        bytes calldata context\n    ) external pure override returns (bytes memory) {\n        bytes4 selector = bytes4(data);\n        if (\n            selector == IAddrResolver.addr.selector ||\n            selector == IAddressResolver.addr.selector\n        ) {\n            if (selector == IAddressResolver.addr.selector) {\n                (, uint256 coinType) = abi.decode(data[4:], (bytes32, uint256));\n                if (coinType != COIN_TYPE_ETH) return abi.encode(\"\");\n            }\n            (address record, bool valid) = context.hexToAddress(\n                2,\n                context.length\n            );\n            if (!valid) revert InvalidAddressFormat();\n            return abi.encode(record);\n        }\n        revert NotImplemented();\n    }\n}\n"
    },
    "contracts/resolvers/profiles/IABIResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface IABIResolver {\n    event ABIChanged(bytes32 indexed node, uint256 indexed contentType);\n\n    /**\n     * Returns the ABI associated with an ENS node.\n     * Defined in EIP205.\n     * @param node The ENS node to query\n     * @param contentTypes A bitwise OR of the ABI formats accepted by the caller.\n     * @return contentType The content type of the return value\n     * @return data The ABI data\n     */\n    function ABI(\n        bytes32 node,\n        uint256 contentTypes\n    ) external view returns (uint256, bytes memory);\n}\n"
    },
    "contracts/resolvers/profiles/IAddressResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\n/**\n * Interface for the new (multicoin) addr function.\n */\ninterface IAddressResolver {\n    event AddressChanged(\n        bytes32 indexed node,\n        uint256 coinType,\n        bytes newAddress\n    );\n\n    function addr(\n        bytes32 node,\n        uint256 coinType\n    ) external view returns (bytes memory);\n}\n"
    },
    "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"
    },
    "contracts/resolvers/profiles/IContentHashResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface IContentHashResolver {\n    event ContenthashChanged(bytes32 indexed node, bytes hash);\n\n    /**\n     * Returns the contenthash associated with an ENS node.\n     * @param node The ENS node to query.\n     * @return The associated contenthash.\n     */\n    function contenthash(bytes32 node) external view returns (bytes memory);\n}\n"
    },
    "contracts/resolvers/profiles/IDNSRecordResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface IDNSRecordResolver {\n    // DNSRecordChanged is emitted whenever a given node/name/resource's RRSET is updated.\n    event DNSRecordChanged(\n        bytes32 indexed node,\n        bytes name,\n        uint16 resource,\n        bytes record\n    );\n    // DNSRecordDeleted is emitted whenever a given node/name/resource's RRSET is deleted.\n    event DNSRecordDeleted(bytes32 indexed node, bytes name, uint16 resource);\n\n    /**\n     * Obtain a DNS record.\n     * @param node the namehash of the node for which to fetch the record\n     * @param name the keccak-256 hash of the fully-qualified name for which to fetch the record\n     * @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types\n     * @return the DNS record in wire format if present, otherwise empty\n     */\n    function dnsRecord(\n        bytes32 node,\n        bytes32 name,\n        uint16 resource\n    ) external view returns (bytes memory);\n}\n"
    },
    "contracts/resolvers/profiles/IDNSZoneResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface IDNSZoneResolver {\n    // DNSZonehashChanged is emitted whenever a given node's zone hash is updated.\n    event DNSZonehashChanged(\n        bytes32 indexed node,\n        bytes lastzonehash,\n        bytes zonehash\n    );\n\n    /**\n     * zonehash obtains the hash for the zone.\n     * @param node The ENS node to query.\n     * @return The associated contenthash.\n     */\n    function zonehash(bytes32 node) external view returns (bytes memory);\n}\n"
    },
    "contracts/resolvers/profiles/IExtendedDNSResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IExtendedDNSResolver {\n    function resolve(\n        bytes memory name,\n        bytes memory data,\n        bytes memory context\n    ) external view returns (bytes memory);\n}\n"
    },
    "contracts/resolvers/profiles/IExtendedResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IExtendedResolver {\n    function resolve(\n        bytes memory name,\n        bytes memory data\n    ) external view returns (bytes memory);\n}\n"
    },
    "contracts/resolvers/profiles/IInterfaceResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface IInterfaceResolver {\n    event InterfaceChanged(\n        bytes32 indexed node,\n        bytes4 indexed interfaceID,\n        address implementer\n    );\n\n    /**\n     * Returns the address of a contract that implements the specified interface for this name.\n     * If an implementer has not been set for this interfaceID and name, the resolver will query\n     * the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that\n     * contract implements EIP165 and returns `true` for the specified interfaceID, its address\n     * will be returned.\n     * @param node The ENS node to query.\n     * @param interfaceID The EIP 165 interface ID to check for.\n     * @return The address that implements this interface, or 0 if the interface is unsupported.\n     */\n    function interfaceImplementer(\n        bytes32 node,\n        bytes4 interfaceID\n    ) external view returns (address);\n}\n"
    },
    "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"
    },
    "contracts/resolvers/profiles/IPubkeyResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface IPubkeyResolver {\n    event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);\n\n    /**\n     * Returns the SECP256k1 public key associated with an ENS node.\n     * Defined in EIP 619.\n     * @param node The ENS node to query\n     * @return x The X coordinate of the curve point for the public key.\n     * @return y The Y coordinate of the curve point for the public key.\n     */\n    function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);\n}\n"
    },
    "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"
    },
    "contracts/resolvers/profiles/IVersionableResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface IVersionableResolver {\n    event VersionChanged(bytes32 indexed node, uint64 newVersion);\n\n    function recordVersions(bytes32 node) external view returns (uint64);\n}\n"
    },
    "contracts/resolvers/Resolver.sol": {
      "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\nimport \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport \"./profiles/IABIResolver.sol\";\nimport \"./profiles/IAddressResolver.sol\";\nimport \"./profiles/IAddrResolver.sol\";\nimport \"./profiles/IContentHashResolver.sol\";\nimport \"./profiles/IDNSRecordResolver.sol\";\nimport \"./profiles/IDNSZoneResolver.sol\";\nimport \"./profiles/IInterfaceResolver.sol\";\nimport \"./profiles/INameResolver.sol\";\nimport \"./profiles/IPubkeyResolver.sol\";\nimport \"./profiles/ITextResolver.sol\";\nimport \"./profiles/IExtendedResolver.sol\";\n\n/**\n * A generic resolver interface which includes all the functions including the ones deprecated\n */\ninterface Resolver is\n    IERC165,\n    IABIResolver,\n    IAddressResolver,\n    IAddrResolver,\n    IContentHashResolver,\n    IDNSRecordResolver,\n    IDNSZoneResolver,\n    IInterfaceResolver,\n    INameResolver,\n    IPubkeyResolver,\n    ITextResolver,\n    IExtendedResolver\n{\n    /* Deprecated events */\n    event ContentChanged(bytes32 indexed node, bytes32 hash);\n\n    function setApprovalForAll(address, bool) external;\n\n    function approve(bytes32 node, address delegate, bool approved) external;\n\n    function isApprovedForAll(address account, address operator) external;\n\n    function isApprovedFor(\n        address owner,\n        bytes32 node,\n        address delegate\n    ) external;\n\n    function setABI(\n        bytes32 node,\n        uint256 contentType,\n        bytes calldata data\n    ) external;\n\n    function setAddr(bytes32 node, address addr) external;\n\n    function setAddr(bytes32 node, uint256 coinType, bytes calldata a) external;\n\n    function setContenthash(bytes32 node, bytes calldata hash) external;\n\n    function setDnsrr(bytes32 node, bytes calldata data) external;\n\n    function setName(bytes32 node, string calldata _name) external;\n\n    function setPubkey(bytes32 node, bytes32 x, bytes32 y) external;\n\n    function setText(\n        bytes32 node,\n        string calldata key,\n        string calldata value\n    ) external;\n\n    function setInterface(\n        bytes32 node,\n        bytes4 interfaceID,\n        address implementer\n    ) external;\n\n    function multicall(\n        bytes[] calldata data\n    ) external returns (bytes[] memory results);\n\n    function multicallWithNodeCheck(\n        bytes32 nodehash,\n        bytes[] calldata data\n    ) external returns (bytes[] memory results);\n\n    /* Deprecated functions */\n    function content(bytes32 node) external view returns (bytes32);\n\n    function multihash(bytes32 node) external view returns (bytes memory);\n\n    function setContent(bytes32 node, bytes32 hash) external;\n\n    function setMultihash(bytes32 node, bytes calldata hash) external;\n}\n"
    },
    "contracts/resolvers/ResolverBase.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport \"./profiles/IVersionableResolver.sol\";\n\nabstract contract ResolverBase is ERC165, IVersionableResolver {\n    mapping(bytes32 => uint64) public recordVersions;\n\n    function isAuthorised(bytes32 node) internal view virtual returns (bool);\n\n    modifier authorised(bytes32 node) {\n        require(isAuthorised(node));\n        _;\n    }\n\n    /**\n     * Increments the record version associated with an ENS node.\n     * May only be called by the owner of that node in the ENS registry.\n     * @param node The node to update.\n     */\n    function clearRecords(bytes32 node) public virtual authorised(node) {\n        recordVersions[node]++;\n        emit VersionChanged(node, recordVersions[node]);\n    }\n\n    function supportsInterface(\n        bytes4 interfaceID\n    ) public view virtual override returns (bool) {\n        return\n            interfaceID == type(IVersionableResolver).interfaceId ||\n            super.supportsInterface(interfaceID);\n    }\n}\n"
    },
    "contracts/root/Controllable.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract Controllable is Ownable {\n    mapping(address => bool) public controllers;\n\n    event ControllerChanged(address indexed controller, bool enabled);\n\n    modifier onlyController() {\n        require(\n            controllers[msg.sender],\n            \"Controllable: Caller is not a controller\"\n        );\n        _;\n    }\n\n    function setController(address controller, bool enabled) public onlyOwner {\n        controllers[controller] = enabled;\n        emit ControllerChanged(controller, enabled);\n    }\n}\n"
    },
    "contracts/root/Root.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"../registry/ENS.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./Controllable.sol\";\n\ncontract Root is Ownable, Controllable {\n    bytes32 private constant ROOT_NODE = bytes32(0);\n\n    bytes4 private constant INTERFACE_META_ID =\n        bytes4(keccak256(\"supportsInterface(bytes4)\"));\n\n    event TLDLocked(bytes32 indexed label);\n\n    ENS public ens;\n    mapping(bytes32 => bool) public locked;\n\n    constructor(ENS _ens) public {\n        ens = _ens;\n    }\n\n    function setSubnodeOwner(\n        bytes32 label,\n        address owner\n    ) external onlyController {\n        require(!locked[label]);\n        ens.setSubnodeOwner(ROOT_NODE, label, owner);\n    }\n\n    function setResolver(address resolver) external onlyOwner {\n        ens.setResolver(ROOT_NODE, resolver);\n    }\n\n    function lock(bytes32 label) external onlyOwner {\n        emit TLDLocked(label);\n        locked[label] = true;\n    }\n\n    function supportsInterface(\n        bytes4 interfaceID\n    ) external pure returns (bool) {\n        return interfaceID == INTERFACE_META_ID;\n    }\n}\n"
    },
    "contracts/utils/HexUtils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nlibrary HexUtils {\n    /**\n     * @dev Attempts to parse bytes32 from a hex string\n     * @param str The string to parse\n     * @param idx The offset to start parsing at\n     * @param lastIdx The (exclusive) last index in `str` to consider. Use `str.length` to scan the whole string.\n     */\n    function hexStringToBytes32(\n        bytes memory str,\n        uint256 idx,\n        uint256 lastIdx\n    ) internal pure returns (bytes32 r, bool valid) {\n        uint256 hexLength = lastIdx - idx;\n        if ((hexLength != 64 && hexLength != 40) || hexLength % 2 == 1) {\n            revert(\"Invalid string length\");\n        }\n        valid = true;\n        assembly {\n            // check that the index to read to is not past the end of the string\n            if gt(lastIdx, mload(str)) {\n                revert(0, 0)\n            }\n\n            function getHex(c) -> ascii {\n                // chars 48-57: 0-9\n                if and(gt(c, 47), lt(c, 58)) {\n                    ascii := sub(c, 48)\n                    leave\n                }\n                // chars 65-70: A-F\n                if and(gt(c, 64), lt(c, 71)) {\n                    ascii := add(sub(c, 65), 10)\n                    leave\n                }\n                // chars 97-102: a-f\n                if and(gt(c, 96), lt(c, 103)) {\n                    ascii := add(sub(c, 97), 10)\n                    leave\n                }\n                // invalid char\n                ascii := 0xff\n            }\n\n            let ptr := add(str, 32)\n            for {\n                let i := idx\n            } lt(i, lastIdx) {\n                i := add(i, 2)\n            } {\n                let byte1 := getHex(byte(0, mload(add(ptr, i))))\n                let byte2 := getHex(byte(0, mload(add(ptr, add(i, 1)))))\n                // if either byte is invalid, set invalid and break loop\n                if or(eq(byte1, 0xff), eq(byte2, 0xff)) {\n                    valid := false\n                    break\n                }\n                let combined := or(shl(4, byte1), byte2)\n                r := or(shl(8, r), combined)\n            }\n        }\n    }\n\n    /**\n     * @dev Attempts to parse an address from a hex string\n     * @param str The string to parse\n     * @param idx The offset to start parsing at\n     * @param lastIdx The (exclusive) last index in `str` to consider. Use `str.length` to scan the whole string.\n     */\n    function hexToAddress(\n        bytes memory str,\n        uint256 idx,\n        uint256 lastIdx\n    ) internal pure returns (address, bool) {\n        if (lastIdx - idx < 40) return (address(0x0), false);\n        (bytes32 r, bool valid) = hexStringToBytes32(str, idx, lastIdx);\n        return (address(uint160(uint256(r))), valid);\n    }\n}\n"
    },
    "contracts/utils/LowLevelCallUtils.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.13;\n\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n\nlibrary LowLevelCallUtils {\n    using Address for address;\n\n    /**\n     * @dev Makes a static call to the specified `target` with `data`. Return data can be fetched with\n     *      `returnDataSize` and `readReturnData`.\n     * @param target The address to staticcall.\n     * @param data The data to pass to the call.\n     * @return success True if the call succeeded, or false if it reverts.\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data\n    ) internal view returns (bool success) {\n        require(\n            target.isContract(),\n            \"LowLevelCallUtils: static call to non-contract\"\n        );\n        assembly {\n            success := staticcall(\n                gas(),\n                target,\n                add(data, 32),\n                mload(data),\n                0,\n                0\n            )\n        }\n    }\n\n    /**\n     * @dev Returns the size of the return data of the most recent external call.\n     */\n    function returnDataSize() internal pure returns (uint256 len) {\n        assembly {\n            len := returndatasize()\n        }\n    }\n\n    /**\n     * @dev Reads return data from the most recent external call.\n     * @param offset Offset into the return data.\n     * @param length Number of bytes to return.\n     */\n    function readReturnData(\n        uint256 offset,\n        uint256 length\n    ) internal pure returns (bytes memory data) {\n        data = new bytes(length);\n        assembly {\n            returndatacopy(add(data, 32), offset, length)\n        }\n    }\n\n    /**\n     * @dev Reverts with the return data from the most recent external call.\n     */\n    function propagateRevert() internal pure {\n        assembly {\n            returndatacopy(0, 0, returndatasize())\n            revert(0, returndatasize())\n        }\n    }\n}\n"
    },
    "contracts/utils/NameEncoder.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\nimport {BytesUtils} from \"../wrapper/BytesUtils.sol\";\n\nlibrary NameEncoder {\n    using BytesUtils for bytes;\n\n    function dnsEncodeName(\n        string memory name\n    ) internal pure returns (bytes memory dnsName, bytes32 node) {\n        uint8 labelLength = 0;\n        bytes memory bytesName = bytes(name);\n        uint256 length = bytesName.length;\n        dnsName = new bytes(length + 2);\n        node = 0;\n        if (length == 0) {\n            dnsName[0] = 0;\n            return (dnsName, node);\n        }\n\n        // use unchecked to save gas since we check for an underflow\n        // and we check for the length before the loop\n        unchecked {\n            for (uint256 i = length - 1; i >= 0; i--) {\n                if (bytesName[i] == \".\") {\n                    dnsName[i + 1] = bytes1(labelLength);\n                    node = keccak256(\n                        abi.encodePacked(\n                            node,\n                            bytesName.keccak(i + 1, labelLength)\n                        )\n                    );\n                    labelLength = 0;\n                } else {\n                    labelLength += 1;\n                    dnsName[i + 1] = bytesName[i];\n                }\n                if (i == 0) {\n                    break;\n                }\n            }\n        }\n\n        node = keccak256(\n            abi.encodePacked(node, bytesName.keccak(0, labelLength))\n        );\n\n        dnsName[0] = bytes1(labelLength);\n        return (dnsName, node);\n    }\n}\n"
    },
    "contracts/utils/TestHexUtils.sol": {
      "content": "//SPDX-License-Identifier: MIT\npragma solidity ~0.8.17;\n\nimport {HexUtils} from \"./HexUtils.sol\";\n\ncontract TestHexUtils {\n    using HexUtils for *;\n\n    function hexStringToBytes32(\n        bytes calldata name,\n        uint256 idx,\n        uint256 lastInx\n    ) public pure returns (bytes32, bool) {\n        return name.hexStringToBytes32(idx, lastInx);\n    }\n\n    function hexToAddress(\n        bytes calldata input,\n        uint256 idx,\n        uint256 lastInx\n    ) public pure returns (address, bool) {\n        return input.hexToAddress(idx, lastInx);\n    }\n}\n"
    },
    "contracts/utils/UniversalResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.17 <0.9.0;\n\nimport {ERC165} from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {LowLevelCallUtils} from \"./LowLevelCallUtils.sol\";\nimport {ENS} from \"../registry/ENS.sol\";\nimport {IExtendedResolver} from \"../resolvers/profiles/IExtendedResolver.sol\";\nimport {Resolver, INameResolver, IAddrResolver} from \"../resolvers/Resolver.sol\";\nimport {NameEncoder} from \"./NameEncoder.sol\";\nimport {BytesUtils} from \"../wrapper/BytesUtils.sol\";\nimport {HexUtils} from \"./HexUtils.sol\";\n\nerror OffchainLookup(\n    address sender,\n    string[] urls,\n    bytes callData,\n    bytes4 callbackFunction,\n    bytes extraData\n);\n\nerror ResolverNotFound();\n\nerror ResolverWildcardNotSupported();\n\nstruct MulticallData {\n    bytes name;\n    bytes[] data;\n    string[] gateways;\n    bytes4 callbackFunction;\n    bool isWildcard;\n    address resolver;\n    bytes metaData;\n    bool[] failures;\n}\n\nstruct OffchainLookupCallData {\n    address sender;\n    string[] urls;\n    bytes callData;\n}\n\nstruct OffchainLookupExtraData {\n    bytes4 callbackFunction;\n    bytes data;\n}\n\ninterface BatchGateway {\n    function query(\n        OffchainLookupCallData[] memory data\n    ) external returns (bool[] memory failures, bytes[] memory responses);\n}\n\n/**\n * The Universal Resolver is a contract that handles the work of resolving a name entirely onchain,\n * making it possible to make a single smart contract call to resolve an ENS name.\n */\ncontract UniversalResolver is ERC165, Ownable {\n    using Address for address;\n    using NameEncoder for string;\n    using BytesUtils for bytes;\n    using HexUtils for bytes;\n\n    string[] public batchGatewayURLs;\n    ENS public immutable registry;\n\n    constructor(address _registry, string[] memory _urls) {\n        registry = ENS(_registry);\n        batchGatewayURLs = _urls;\n    }\n\n    function setGatewayURLs(string[] memory _urls) public onlyOwner {\n        batchGatewayURLs = _urls;\n    }\n\n    /**\n     * @dev Performs ENS name resolution for the supplied name and resolution data.\n     * @param name The name to resolve, in normalised and DNS-encoded form.\n     * @param data The resolution data, as specified in ENSIP-10.\n     * @return The result of resolving the name.\n     */\n    function resolve(\n        bytes calldata name,\n        bytes memory data\n    ) external view returns (bytes memory, address) {\n        return\n            _resolveSingle(\n                name,\n                data,\n                batchGatewayURLs,\n                this.resolveSingleCallback.selector,\n                \"\"\n            );\n    }\n\n    function resolve(\n        bytes calldata name,\n        bytes[] memory data\n    ) external view returns (bytes[] memory, address) {\n        return resolve(name, data, batchGatewayURLs);\n    }\n\n    function resolve(\n        bytes calldata name,\n        bytes memory data,\n        string[] memory gateways\n    ) external view returns (bytes memory, address) {\n        return\n            _resolveSingle(\n                name,\n                data,\n                gateways,\n                this.resolveSingleCallback.selector,\n                \"\"\n            );\n    }\n\n    function resolve(\n        bytes calldata name,\n        bytes[] memory data,\n        string[] memory gateways\n    ) public view returns (bytes[] memory, address) {\n        return\n            _resolve(name, data, gateways, this.resolveCallback.selector, \"\");\n    }\n\n    function _resolveSingle(\n        bytes calldata name,\n        bytes memory data,\n        string[] memory gateways,\n        bytes4 callbackFunction,\n        bytes memory metaData\n    ) public view returns (bytes memory, address) {\n        bytes[] memory dataArr = new bytes[](1);\n        dataArr[0] = data;\n        (bytes[] memory results, address resolver) = _resolve(\n            name,\n            dataArr,\n            gateways,\n            callbackFunction,\n            metaData\n        );\n        return (results[0], resolver);\n    }\n\n    function _resolve(\n        bytes calldata name,\n        bytes[] memory data,\n        string[] memory gateways,\n        bytes4 callbackFunction,\n        bytes memory metaData\n    ) internal view returns (bytes[] memory results, address resolverAddress) {\n        (Resolver resolver, , uint256 finalOffset) = findResolver(name);\n        resolverAddress = address(resolver);\n        if (resolverAddress == address(0)) {\n            revert ResolverNotFound();\n        }\n\n        bool isWildcard = finalOffset != 0;\n\n        results = _multicall(\n            MulticallData(\n                name,\n                data,\n                gateways,\n                callbackFunction,\n                isWildcard,\n                resolverAddress,\n                metaData,\n                new bool[](data.length)\n            )\n        );\n    }\n\n    function reverse(\n        bytes calldata reverseName\n    ) external view returns (string memory, address, address, address) {\n        return reverse(reverseName, batchGatewayURLs);\n    }\n\n    /**\n     * @dev Performs ENS name reverse resolution for the supplied reverse name.\n     * @param reverseName The reverse name to resolve, in normalised and DNS-encoded form. e.g. b6E040C9ECAaE172a89bD561c5F73e1C48d28cd9.addr.reverse\n     * @return The resolved name, the resolved address, the reverse resolver address, and the resolver address.\n     */\n    function reverse(\n        bytes calldata reverseName,\n        string[] memory gateways\n    ) public view returns (string memory, address, address, address) {\n        bytes memory encodedCall = abi.encodeCall(\n            INameResolver.name,\n            reverseName.namehash(0)\n        );\n        (\n            bytes memory resolvedReverseData,\n            address reverseResolverAddress\n        ) = _resolveSingle(\n                reverseName,\n                encodedCall,\n                gateways,\n                this.reverseCallback.selector,\n                \"\"\n            );\n\n        return\n            getForwardDataFromReverse(\n                resolvedReverseData,\n                reverseResolverAddress,\n                gateways\n            );\n    }\n\n    function getForwardDataFromReverse(\n        bytes memory resolvedReverseData,\n        address reverseResolverAddress,\n        string[] memory gateways\n    ) internal view returns (string memory, address, address, address) {\n        string memory resolvedName = abi.decode(resolvedReverseData, (string));\n\n        (bytes memory encodedName, bytes32 namehash) = resolvedName\n            .dnsEncodeName();\n\n        bytes memory encodedCall = abi.encodeCall(IAddrResolver.addr, namehash);\n        bytes memory metaData = abi.encode(\n            resolvedName,\n            reverseResolverAddress\n        );\n        (bytes memory resolvedData, address resolverAddress) = this\n            ._resolveSingle(\n                encodedName,\n                encodedCall,\n                gateways,\n                this.reverseCallback.selector,\n                metaData\n            );\n\n        address resolvedAddress = abi.decode(resolvedData, (address));\n\n        return (\n            resolvedName,\n            resolvedAddress,\n            reverseResolverAddress,\n            resolverAddress\n        );\n    }\n\n    function resolveSingleCallback(\n        bytes calldata response,\n        bytes calldata extraData\n    ) external view returns (bytes memory, address) {\n        (bytes[] memory results, address resolver, , ) = _resolveCallback(\n            response,\n            extraData,\n            this.resolveSingleCallback.selector\n        );\n        return (results[0], resolver);\n    }\n\n    function resolveCallback(\n        bytes calldata response,\n        bytes calldata extraData\n    ) external view returns (bytes[] memory, address) {\n        (bytes[] memory results, address resolver, , ) = _resolveCallback(\n            response,\n            extraData,\n            this.resolveCallback.selector\n        );\n        return (results, resolver);\n    }\n\n    function reverseCallback(\n        bytes calldata response,\n        bytes calldata extraData\n    ) external view returns (string memory, address, address, address) {\n        (\n            bytes[] memory resolvedData,\n            address resolverAddress,\n            string[] memory gateways,\n            bytes memory metaData\n        ) = _resolveCallback(\n                response,\n                extraData,\n                this.reverseCallback.selector\n            );\n\n        if (metaData.length > 0) {\n            (string memory resolvedName, address reverseResolverAddress) = abi\n                .decode(metaData, (string, address));\n            address resolvedAddress = abi.decode(resolvedData[0], (address));\n            return (\n                resolvedName,\n                resolvedAddress,\n                reverseResolverAddress,\n                resolverAddress\n            );\n        }\n\n        return\n            getForwardDataFromReverse(\n                resolvedData[0],\n                resolverAddress,\n                gateways\n            );\n    }\n\n    function supportsInterface(\n        bytes4 interfaceId\n    ) public view virtual override returns (bool) {\n        return\n            interfaceId == type(IExtendedResolver).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    function _resolveCallback(\n        bytes calldata response,\n        bytes calldata extraData,\n        bytes4 callbackFunction\n    )\n        internal\n        view\n        returns (bytes[] memory, address, string[] memory, bytes memory)\n    {\n        MulticallData memory multicallData;\n        multicallData.callbackFunction = callbackFunction;\n        (bool[] memory failures, bytes[] memory responses) = abi.decode(\n            response,\n            (bool[], bytes[])\n        );\n        OffchainLookupExtraData[] memory extraDatas;\n        (\n            multicallData.isWildcard,\n            multicallData.resolver,\n            multicallData.gateways,\n            multicallData.metaData,\n            extraDatas\n        ) = abi.decode(\n            extraData,\n            (bool, address, string[], bytes, OffchainLookupExtraData[])\n        );\n        require(responses.length <= extraDatas.length);\n        multicallData.data = new bytes[](extraDatas.length);\n        multicallData.failures = new bool[](extraDatas.length);\n        uint256 offchainCount = 0;\n        for (uint256 i = 0; i < extraDatas.length; i++) {\n            if (extraDatas[i].callbackFunction == bytes4(0)) {\n                // This call did not require an offchain lookup; use the previous input data.\n                multicallData.data[i] = extraDatas[i].data;\n            } else {\n                if (failures[offchainCount]) {\n                    multicallData.failures[i] = true;\n                    multicallData.data[i] = responses[offchainCount];\n                } else {\n                    multicallData.data[i] = abi.encodeWithSelector(\n                        extraDatas[i].callbackFunction,\n                        responses[offchainCount],\n                        extraDatas[i].data\n                    );\n                }\n                offchainCount = offchainCount + 1;\n            }\n        }\n\n        return (\n            _multicall(multicallData),\n            multicallData.resolver,\n            multicallData.gateways,\n            multicallData.metaData\n        );\n    }\n\n    /**\n     * @dev Makes a call to `target` with `data`. If the call reverts with an `OffchainLookup` error, wraps\n     *      the error with the data necessary to continue the request where it left off.\n     * @param target The address to call.\n     * @param data The data to call `target` with.\n     * @return offchain Whether the call reverted with an `OffchainLookup` error.\n     * @return returnData If `target` did not revert, contains the return data from the call to `target`. Otherwise, contains a `OffchainLookupCallData` struct.\n     * @return extraData If `target` did not revert, is empty. Otherwise, contains a `OffchainLookupExtraData` struct.\n     * @return result Whether the call succeeded.\n     */\n    function callWithOffchainLookupPropagation(\n        address target,\n        bytes memory data\n    )\n        internal\n        view\n        returns (\n            bool offchain,\n            bytes memory returnData,\n            OffchainLookupExtraData memory extraData,\n            bool result\n        )\n    {\n        result = LowLevelCallUtils.functionStaticCall(address(target), data);\n        uint256 size = LowLevelCallUtils.returnDataSize();\n\n        if (result) {\n            return (\n                false,\n                LowLevelCallUtils.readReturnData(0, size),\n                extraData,\n                true\n            );\n        }\n\n        // Failure\n        if (size >= 4) {\n            bytes memory errorId = LowLevelCallUtils.readReturnData(0, 4);\n            // Offchain lookup. Decode the revert message and create our own that nests it.\n            bytes memory revertData = LowLevelCallUtils.readReturnData(\n                4,\n                size - 4\n            );\n            if (bytes4(errorId) == OffchainLookup.selector) {\n                (\n                    address wrappedSender,\n                    string[] memory wrappedUrls,\n                    bytes memory wrappedCallData,\n                    bytes4 wrappedCallbackFunction,\n                    bytes memory wrappedExtraData\n                ) = abi.decode(\n                        revertData,\n                        (address, string[], bytes, bytes4, bytes)\n                    );\n                if (wrappedSender == target) {\n                    returnData = abi.encode(\n                        OffchainLookupCallData(\n                            wrappedSender,\n                            wrappedUrls,\n                            wrappedCallData\n                        )\n                    );\n                    extraData = OffchainLookupExtraData(\n                        wrappedCallbackFunction,\n                        wrappedExtraData\n                    );\n                    return (true, returnData, extraData, false);\n                }\n            } else {\n                returnData = bytes.concat(errorId, revertData);\n                return (false, returnData, extraData, false);\n            }\n        }\n    }\n\n    /**\n     * @dev Finds a resolver by recursively querying the registry, starting at the longest name and progressively\n     *      removing labels until it finds a result.\n     * @param name The name to resolve, in DNS-encoded and normalised form.\n     * @return resolver The Resolver responsible for this name.\n     * @return namehash The namehash of the full name.\n     * @return finalOffset The offset of the first label with a resolver.\n     */\n    function findResolver(\n        bytes calldata name\n    ) public view returns (Resolver, bytes32, uint256) {\n        (\n            address resolver,\n            bytes32 namehash,\n            uint256 finalOffset\n        ) = findResolver(name, 0);\n        return (Resolver(resolver), namehash, finalOffset);\n    }\n\n    function findResolver(\n        bytes calldata name,\n        uint256 offset\n    ) internal view returns (address, bytes32, uint256) {\n        uint256 labelLength = uint256(uint8(name[offset]));\n        if (labelLength == 0) {\n            return (address(0), bytes32(0), offset);\n        }\n        uint256 nextLabel = offset + labelLength + 1;\n        bytes32 labelHash;\n        if (\n            labelLength == 66 &&\n            // 0x5b == '['\n            name[offset + 1] == 0x5b &&\n            // 0x5d == ']'\n            name[nextLabel - 1] == 0x5d\n        ) {\n            // Encrypted label\n            (labelHash, ) = bytes(name[offset + 2:nextLabel - 1])\n                .hexStringToBytes32(0, 64);\n        } else {\n            labelHash = keccak256(name[offset + 1:nextLabel]);\n        }\n        (\n            address parentresolver,\n            bytes32 parentnode,\n            uint256 parentoffset\n        ) = findResolver(name, nextLabel);\n        bytes32 node = keccak256(abi.encodePacked(parentnode, labelHash));\n        address resolver = registry.resolver(node);\n        if (resolver != address(0)) {\n            return (resolver, node, offset);\n        }\n        return (parentresolver, node, parentoffset);\n    }\n\n    function _hasExtendedResolver(\n        address resolver\n    ) internal view returns (bool) {\n        try\n            Resolver(resolver).supportsInterface{gas: 50000}(\n                type(IExtendedResolver).interfaceId\n            )\n        returns (bool supported) {\n            return supported;\n        } catch {\n            return false;\n        }\n    }\n\n    function _multicall(\n        MulticallData memory multicallData\n    ) internal view returns (bytes[] memory results) {\n        uint256 length = multicallData.data.length;\n        uint256 offchainCount = 0;\n        OffchainLookupCallData[]\n            memory callDatas = new OffchainLookupCallData[](length);\n        OffchainLookupExtraData[]\n            memory extraDatas = new OffchainLookupExtraData[](length);\n        results = new bytes[](length);\n        bool isCallback = multicallData.name.length == 0;\n        bool hasExtendedResolver = _hasExtendedResolver(multicallData.resolver);\n\n        if (multicallData.isWildcard && !hasExtendedResolver) {\n            revert ResolverWildcardNotSupported();\n        }\n\n        for (uint256 i = 0; i < length; i++) {\n            bytes memory item = multicallData.data[i];\n            bool failure = multicallData.failures[i];\n            if (failure) {\n                results[i] = item;\n                continue;\n            }\n            if (!isCallback && hasExtendedResolver) {\n                item = abi.encodeCall(\n                    IExtendedResolver.resolve,\n                    (multicallData.name, item)\n                );\n            }\n            (\n                bool offchain,\n                bytes memory returnData,\n                OffchainLookupExtraData memory extraData,\n                bool success\n            ) = callWithOffchainLookupPropagation(multicallData.resolver, item);\n\n            if (offchain) {\n                callDatas[offchainCount] = abi.decode(\n                    returnData,\n                    (OffchainLookupCallData)\n                );\n                extraDatas[i] = extraData;\n                offchainCount += 1;\n                continue;\n            }\n\n            if (success && hasExtendedResolver) {\n                // if this is a successful resolve() call, unwrap the result\n                returnData = abi.decode(returnData, (bytes));\n            }\n            results[i] = returnData;\n            extraDatas[i].data = multicallData.data[i];\n        }\n\n        if (offchainCount == 0) {\n            return results;\n        }\n\n        // Trim callDatas if offchain data exists\n        assembly {\n            mstore(callDatas, offchainCount)\n        }\n\n        revert OffchainLookup(\n            address(this),\n            multicallData.gateways,\n            abi.encodeWithSelector(BatchGateway.query.selector, callDatas),\n            multicallData.callbackFunction,\n            abi.encode(\n                multicallData.isWildcard,\n                multicallData.resolver,\n                multicallData.gateways,\n                multicallData.metaData,\n                extraDatas\n            )\n        );\n    }\n}\n"
    },
    "contracts/wrapper/BytesUtils.sol": {
      "content": "//SPDX-License-Identifier: MIT\npragma solidity ~0.8.17;\n\nlibrary BytesUtils {\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 the ENS namehash of a DNS-encoded name.\n     * @param self The DNS-encoded name to hash.\n     * @param offset The offset at which to start hashing.\n     * @return The namehash of the name.\n     */\n    function namehash(\n        bytes memory self,\n        uint256 offset\n    ) internal pure returns (bytes32) {\n        (bytes32 labelhash, uint256 newOffset) = readLabel(self, offset);\n        if (labelhash == bytes32(0)) {\n            require(offset == self.length - 1, \"namehash: Junk at end of name\");\n            return bytes32(0);\n        }\n        return\n            keccak256(abi.encodePacked(namehash(self, newOffset), labelhash));\n    }\n\n    /**\n     * @dev Returns the keccak-256 hash of a DNS-encoded label, and the offset to the start of the next label.\n     * @param self The byte string to read a label from.\n     * @param idx The index to read a label at.\n     * @return labelhash The hash of the label at the specified index, or 0 if it is the last label.\n     * @return newIdx The index of the start of the next label.\n     */\n    function readLabel(\n        bytes memory self,\n        uint256 idx\n    ) internal pure returns (bytes32 labelhash, uint256 newIdx) {\n        require(idx < self.length, \"readLabel: Index out of bounds\");\n        uint256 len = uint256(uint8(self[idx]));\n        if (len > 0) {\n            labelhash = keccak(self, idx + 1, len);\n        } else {\n            labelhash = bytes32(0);\n        }\n        newIdx = idx + len + 1;\n    }\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 1200
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}