{
  "address": "0xF142B308cF687d4358410a4cB885513b30A42025",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "contract ENS",
          "name": "_ens",
          "type": "address"
        },
        {
          "internalType": "contract DNSSEC",
          "name": "_oracle",
          "type": "address"
        },
        {
          "internalType": "string",
          "name": "_gatewayURL",
          "type": "string"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "name",
          "type": "bytes"
        }
      ],
      "name": "CouldNotResolve",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "InvalidOperation",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "sender",
          "type": "address"
        },
        {
          "internalType": "string[]",
          "name": "urls",
          "type": "string[]"
        },
        {
          "internalType": "bytes",
          "name": "callData",
          "type": "bytes"
        },
        {
          "internalType": "bytes4",
          "name": "callbackFunction",
          "type": "bytes4"
        },
        {
          "internalType": "bytes",
          "name": "extraData",
          "type": "bytes"
        }
      ],
      "name": "OffchainLookup",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "ens",
      "outputs": [
        {
          "internalType": "contract ENS",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "gatewayURL",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "oracle",
      "outputs": [
        {
          "internalType": "contract DNSSEC",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "name",
          "type": "bytes"
        },
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        }
      ],
      "name": "resolve",
      "outputs": [
        {
          "internalType": "bytes",
          "name": "",
          "type": "bytes"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "response",
          "type": "bytes"
        },
        {
          "internalType": "bytes",
          "name": "extraData",
          "type": "bytes"
        }
      ],
      "name": "resolveCallback",
      "outputs": [
        {
          "internalType": "bytes",
          "name": "",
          "type": "bytes"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes4",
          "name": "interfaceId",
          "type": "bytes4"
        }
      ],
      "name": "supportsInterface",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "pure",
      "type": "function"
    }
  ],
  "transactionHash": "0xf3766f296d6514d11a2caef1366c09fc8d4990a6a1e2849b0a1261b6e33f0994",
  "receipt": {
    "to": null,
    "from": "0x0904Dac3347eA47d208F3Fd67402D039a3b99859",
    "contractAddress": "0xF142B308cF687d4358410a4cB885513b30A42025",
    "transactionIndex": 99,
    "gasUsed": "1860432",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0xf5441d1eeefc3e10593222ed48649d2cb17282b669f65b3a54b0d59ca1bd592b",
    "transactionHash": "0xf3766f296d6514d11a2caef1366c09fc8d4990a6a1e2849b0a1261b6e33f0994",
    "logs": [],
    "blockNumber": 19020689,
    "cumulativeGasUsed": "7259998",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
    "0x0fc3152971714E5ed7723FAFa650F86A4BaF30C5",
    "https://dnssec-oracle.ens.domains/"
  ],
  "numDeployments": 1,
  "solcInputHash": "dd9e022689821cffaeb04b9ddbda87ae",
  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract ENS\",\"name\":\"_ens\",\"type\":\"address\"},{\"internalType\":\"contract DNSSEC\",\"name\":\"_oracle\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_gatewayURL\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"CouldNotResolve\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ens\",\"outputs\":[{\"internalType\":\"contract ENS\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gatewayURL\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract DNSSEC\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnsregistrar/OffchainDNSResolver.sol\":\"OffchainDNSResolver\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"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\",\"keccak256\":\"0xd6dd3b0b327288f8e1b711a609f4040fea602e2ad4bba9febdf2f33b4e56eb0c\",\"license\":\"BSD-2-Clause\"},\"@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\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"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, IERC165 {\\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 supportsInterface(\\n        bytes4 interfaceId\\n    ) external pure override returns (bool) {\\n        return interfaceId == type(IExtendedResolver).interfaceId;\\n    }\\n\\n    function resolve(\\n        bytes calldata name,\\n        bytes calldata data\\n    ) external view returns (bytes memory) {\\n        revertWithDefaultOffchainLookup(name, data);\\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, bytes4 selector) = abi.decode(\\n            extraData,\\n            (bytes, bytes, bytes4)\\n        );\\n\\n        if (selector != bytes4(0)) {\\n            (bytes memory targetData, address targetResolver) = abi.decode(\\n                query,\\n                (bytes, address)\\n            );\\n            return\\n                callWithOffchainLookupPropagation(\\n                    targetResolver,\\n                    name,\\n                    query,\\n                    abi.encodeWithSelector(\\n                        selector,\\n                        response,\\n                        abi.encode(targetData, address(this))\\n                    )\\n                );\\n        }\\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            revertWithDefaultOffchainLookup(name, innerdata);\\n        }\\n\\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(0, size);\\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                handleOffchainLookupError(revertData, target, name);\\n            }\\n        }\\n        LowLevelCallUtils.propagateRevert();\\n    }\\n\\n    function revertWithDefaultOffchainLookup(\\n        bytes memory name,\\n        bytes memory data\\n    ) internal view {\\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, data, bytes4(0))\\n        );\\n    }\\n\\n    function handleOffchainLookupError(\\n        bytes memory returnData,\\n        address target,\\n        bytes memory name\\n    ) internal view {\\n        (\\n            address sender,\\n            string[] memory urls,\\n            bytes memory callData,\\n            bytes4 innerCallbackFunction,\\n            bytes memory extraData\\n        ) = abi.decode(returnData, (address, string[], bytes, bytes4, bytes));\\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(name, extraData, innerCallbackFunction)\\n        );\\n    }\\n}\\n\",\"keccak256\":\"0xdd7f8c44e6e73d5c90a942e8059296c5781cd4e2257623aa1eeb5fd3e60aec85\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x4f10902639b85a17ae10745264feff322e793bfb1bc130a9a90efa7dda47c6cc\"},\"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\",\"keccak256\":\"0xee6a236a59e5db8418c98ee4640a91987d26533c02d305cc6c7a37a3ac4ee907\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x4dd68a6efd7c38f6b0e95ca0c056ecb74f88583da650b1a8639e6e78be36fede\"},\"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\",\"keccak256\":\"0x7cb1158c7d268b63de1468e28e2711b28d686e2628ddb22da2149cd93ddeafda\"},\"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\",\"keccak256\":\"0xa7a7a64fb980e521c991415e416fd4106a42f892479805e1daa51ecb0e2e5198\"},\"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\",\"keccak256\":\"0x2ad7f2fc60ebe0f93745fe70247f6a854f66af732483fda2a3c5e055614445e8\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x541f8799c34ff9e7035d09f06ae0f0f8a16b6065e9b60a15670b957321630f72\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x4a8a9c72d6f3effb80b310faa6dc273e7adbc3b949df9c7a42e290e5b13519f3\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x20d3d0d14fab6fc079f90d630a51bb8e274431ca929591ec8d62383ce946cb3a\",\"license\":\"MIT\"}},\"version\":1}",
  "bytecode": "0x60c06040523480156200001157600080fd5b50604051620022743803806200227483398101604081905262000034916200008e565b6001600160a01b03808416608052821660a05260006200005582826200021d565b50505050620002e9565b6001600160a01b03811681146200007557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b600080600060608486031215620000a457600080fd5b8351620000b1816200005f565b80935050602080850151620000c6816200005f565b60408601519093506001600160401b0380821115620000e457600080fd5b818701915087601f830112620000f957600080fd5b8151818111156200010e576200010e62000078565b604051601f8201601f19908116603f0116810190838211818310171562000139576200013962000078565b816040528281528a868487010111156200015257600080fd5b600093505b8284101562000176578484018601518185018701529285019262000157565b60008684830101528096505050505050509250925092565b600181811c90821680620001a357607f821691505b602082108103620001c457634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200021857600081815260208120601f850160051c81016020861015620001f35750805b601f850160051c820191505b818110156200021457828155600101620001ff565b5050505b505050565b81516001600160401b0381111562000239576200023962000078565b62000251816200024a84546200018e565b84620001ca565b602080601f831160018114620002895760008415620002705750858301515b600019600386901b1c1916600185901b17855562000214565b600085815260208120601f198616915b82811015620002ba5788860151825594840194600190910190840162000299565b5085821015620002d95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a051611f586200031c60003960008181610109015261033201526000818160b501526111d50152611f586000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c80637dc0d1d0116100505780637dc0d1d0146101045780639061b9231461012b578063b4a858011461013e57600080fd5b806301ffc9a7146100775780633f15457f146100b057806352539968146100ef575b600080fd5b61009b610085366004611507565b6001600160e01b031916639061b92360e01b1490565b60405190151581526020015b60405180910390f35b6100d77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100a7565b6100f7610151565b6040516100a79190611574565b6100d77f000000000000000000000000000000000000000000000000000000000000000081565b6100f76101393660046115d0565b6101df565b6100f761014c3660046115d0565b61025c565b6000805461015e9061163c565b80601f016020809104026020016040519081016040528092919081815260200182805461018a9061163c565b80156101d75780601f106101ac576101008083540402835291602001916101d7565b820191906000526020600020905b8154815290600101906020018083116101ba57829003601f168201915b505050505081565b606061025485858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815292508791508690819084018382808284376000920191909152506106b792505050565b949350505050565b60606000808061026e85870187611764565b919450925090506001600160e01b031981161561031e576000808380602001905181019061029c9190611841565b91509150610312818686868e8e88306040516020016102bc929190611893565b60408051601f19818403018152908290526102db9392916024016118be565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610848565b95505050505050610254565b600061032c888a018a611920565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bdf95fef836040518263ffffffff1660e01b815260040161037c9190611a2c565b600060405180830381865afa158015610399573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103c19190810190611ab1565b50905060006103d08282610916565b90505b8051516020820151101561069b5760006103f58260000151836020015161097d565b90506104018188610998565b15806104165750606082015161ffff16600114155b8061042a5750604082015161ffff16601014155b15610435575061068d565b60008061044f84600001518560a001518660c001516109bd565b90925090506001600160a01b03821615610689576040516301ffc9a760e01b815263477cc53f60e11b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa1580156104ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d29190611b01565b1561053157610521828a8a8c8c866040516024016104f293929190611b23565b60408051601f198184030181529190526020810180516001600160e01b031663477cc53f60e11b179052610848565b9950505050505050505050610254565b6040516301ffc9a760e01b8152639061b92360e01b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa15801561057c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a09190611b01565b156105ed57610521828a8a8c8c6040516024016105be929190611b5c565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b179052610848565b600080836001600160a01b03168a6040516106089190611b81565b600060405180830381855afa9150503d8060008114610643576040519150601f19603f3d011682016040523d82523d6000602084013e610648565b606091505b50915091508115610665579a506102549950505050505050505050565b8a6040516314d3b60360e11b81526004016106809190611574565b60405180910390fd5b5050505b61069681610b05565b6103d3565b50846040516314d3b60360e11b81526004016106809190611574565b604080516001808252818301909252600091816020015b60608152602001906001900390816106ce579050509050600080546106f29061163c565b80601f016020809104026020016040519081016040528092919081815260200182805461071e9061163c565b801561076b5780601f106107405761010080835404028352916020019161076b565b820191906000526020600020905b81548152906001019060200180831161074e57829003601f168201915b50505050508160008151811061078357610783611b9d565b602002602001018190525030818460106040516024016107a4929190611bb3565b60408051601f19818403018152918152602080830180516001600160e01b03167f31b137b90000000000000000000000000000000000000000000000000000000017905290517fb4a85801000000000000000000000000000000000000000000000000000000009161081d918991899160009101611bd9565b60408051601f1981840301815290829052630556f18360e41b82526106809594939291600401611c19565b60606001600160a01b0385163b6108635761086384846106b7565b600061086f8684610bed565b90503d81156108a5576000610885600083610c7f565b90508080602001905181019061089b9190611cc5565b9350505050610254565b600481106109045760006108bb60006004610c7f565b9050630556f18360e41b6108ce82611cfa565b6001600160e01b031916036109025760006108f360046108ee8186611d48565b610c7f565b9050610900818a8a610cd4565b505b505b61090c610d65565b5050949350505050565b6109646040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261097781610b05565b92915050565b6060600061098b8484610d6f565b9050610254848483610dc9565b6000815183511480156109b657506109b68360008460008751610e4b565b9392505050565b6000606060006109ce868686610e6e565b9050600581511080610a2357506040805180820190915260058082527f454e5331200000000000000000000000000000000000000000000000000000006020830152610a21918391600091908290610e4b565b155b15610a41575050604080516020810190915260008082529150610afd565b6000610a7e6005808451610a559190611d48565b8491907f2000000000000000000000000000000000000000000000000000000000000000610eb8565b90508151811115610ab5576000610a988360058551610f54565b6040805160208101909152600081529095509350610afd92505050565b6000610ac383600584610f54565b905080610af5610ad4846001611d5b565b6001858751610ae39190611d48565b610aed9190611d48565b869190610dc9565b945094505050505b935093915050565b60c08101516020820181905281515111610b1c5750565b6000610b3082600001518360200151610d6f565b8260200151610b3f9190611d5b565b8251909150610b4e908261105e565b61ffff166040830152610b62600282611d5b565b8251909150610b71908261105e565b61ffff166060830152610b85600282611d5b565b8251909150610b949082611086565b63ffffffff166080830152610baa600482611d5b565b8251909150600090610bbc908361105e565b61ffff169050610bcd600283611d5b565b60a084018190529150610be08183611d5b565b60c0909301929092525050565b60006001600160a01b0383163b610c6c5760405162461bcd60e51b815260206004820152602e60248201527f4c6f774c6576656c43616c6c5574696c733a207374617469632063616c6c207460448201527f6f206e6f6e2d636f6e74726163740000000000000000000000000000000000006064820152608401610680565b600080835160208501865afa9392505050565b60608167ffffffffffffffff811115610c9a57610c9a611676565b6040519080825280601f01601f191660200182016040528015610cc4576020820181803683370190505b5090508183602083013e92915050565b600080600080600087806020019051810190610cf09190611d7e565b94509450945094509450866001600160a01b0316856001600160a01b031614610d45576040517f398d4d3200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b30848463b4a8580160e01b89858760405160200161081d93929190611bd9565b3d6000803e3d6000fd5b6000815b83518110610d8357610d83611eb4565b6000610d8f85836110b0565b60ff169050610d9f816001611d5b565b610da99083611d5b565b915080600003610db95750610dbf565b50610d73565b6102548382611d48565b8251606090610dd88385611d5b565b1115610de357600080fd5b60008267ffffffffffffffff811115610dfe57610dfe611676565b6040519080825280601f01601f191660200182016040528015610e28576020820181803683370190505b50905060208082019086860101610e408282876110d4565b509095945050505050565b6000610e5884848461112a565b610e6387878561112a565b149695505050505050565b60606000610e7c85856110b0565b60ff16905082610e8c8286611d5b565b10610e9957610e99611eb4565b610eaf610ea7856001611d5b565b869083610dc9565b95945050505050565b6000835b610ec68486611d5b565b811015610f4757827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916868281518110610f0257610f02611b9d565b01602001517fff000000000000000000000000000000000000000000000000000000000000001603610f35579050610254565b80610f3f81611eca565b915050610ebc565b5060001995945050505050565b6000838381518110610f6857610f68611b9d565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f3000000000000000000000000000000000000000000000000000000000000000148015611020575083610fc5846001611d5b565b81518110610fd557610fd5611b9d565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f7800000000000000000000000000000000000000000000000000000000000000145b156110535760008061103e611036866002611d5b565b87908661114e565b915091508015611050575090506109b6565b50505b61025484848461118a565b815160009061106e836002611d5b565b111561107957600080fd5b50016002015161ffff1690565b8151600090611096836004611d5b565b11156110a157600080fd5b50016004015163ffffffff1690565b60008282815181106110c4576110c4611b9d565b016020015160f81c905092915050565b6020811061110c57815183526110eb602084611d5b565b92506110f8602083611d5b565b9150611105602082611d48565b90506110d4565b905182516020929092036101000a6000190180199091169116179052565b82516000906111398385611d5b565b111561114457600080fd5b5091016020012090565b600080602861115d8585611d48565b101561116e57506000905080610afd565b60008061117c8787876112e7565b909890975095505050505050565b60008061119885858561143b565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018290529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630178b8bf90602401602060405180830381865afa15801561121c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112409190611ee3565b90506001600160a01b03811661125b576000925050506109b6565b6040517f3b3b57de000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b03821690633b3b57de90602401602060405180830381865afa1580156112b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112dd9190611ee3565b9695505050505050565b600080806112f58585611d48565b905080604014158015611309575080602814155b8061131e575061131a600282611f00565b6001145b1561136b5760405162461bcd60e51b815260206004820152601560248201527f496e76616c696420737472696e67206c656e67746800000000000000000000006044820152606401610680565b60019150855184111561137d57600080fd5b6113ce565b6000603a8210602f8311161561139a5750602f190190565b604782106040831116156113b057506036190190565b606782106060831116156113c657506056190190565b5060ff919050565b60208601855b85811015611430576113eb8183015160001a611382565b6113fd6001830184015160001a611382565b60ff811460ff8314171561141657600095505050611430565b60049190911b1760089590951b94909417936002016113d4565b505050935093915050565b6000806114788485875161144f9190611d48565b8791907f2e00000000000000000000000000000000000000000000000000000000000000610eb8565b90506000838210156114a05761149986611493846001611d5b565b8661143b565b90506114a4565b8391505b806114bb866114b38186611d48565b89919061112a565b60408051602081019390935282015260600160405160208183030381529060405280519060200120925050509392505050565b6001600160e01b03198116811461150457600080fd5b50565b60006020828403121561151957600080fd5b81356109b6816114ee565b60005b8381101561153f578181015183820152602001611527565b50506000910152565b60008151808452611560816020860160208601611524565b601f01601f19169290920160200192915050565b6020815260006109b66020830184611548565b60008083601f84011261159957600080fd5b50813567ffffffffffffffff8111156115b157600080fd5b6020830191508360208285010111156115c957600080fd5b9250929050565b600080600080604085870312156115e657600080fd5b843567ffffffffffffffff808211156115fe57600080fd5b61160a88838901611587565b9096509450602087013591508082111561162357600080fd5b5061163087828801611587565b95989497509550505050565b600181811c9082168061165057607f821691505b60208210810361167057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156116af576116af611676565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156116de576116de611676565b604052919050565b600067ffffffffffffffff82111561170057611700611676565b50601f01601f191660200190565b600082601f83011261171f57600080fd5b813561173261172d826116e6565b6116b5565b81815284602083860101111561174757600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561177957600080fd5b833567ffffffffffffffff8082111561179157600080fd5b61179d8783880161170e565b945060208601359150808211156117b357600080fd5b506117c08682870161170e565b92505060408401356117d1816114ee565b809150509250925092565b60006117ea61172d846116e6565b90508281528383830111156117fe57600080fd5b6109b6836020830184611524565b600082601f83011261181d57600080fd5b6109b6838351602085016117dc565b6001600160a01b038116811461150457600080fd5b6000806040838503121561185457600080fd5b825167ffffffffffffffff81111561186b57600080fd5b6118778582860161180c565b92505060208301516118888161182c565b809150509250929050565b6040815260006118a66040830185611548565b90506001600160a01b03831660208301529392505050565b60408152826040820152828460608301376000606084830101526000601f19601f850116820160608382030160208401526112dd6060820185611548565b600067ffffffffffffffff82111561191657611916611676565b5060051b60200190565b6000602080838503121561193357600080fd5b823567ffffffffffffffff8082111561194b57600080fd5b818501915085601f83011261195f57600080fd5b813561196d61172d826118fc565b81815260059190911b8301840190848101908883111561198c57600080fd5b8585015b83811015611a1f578035858111156119a85760008081fd5b86016040818c03601f19018113156119c05760008081fd5b6119c861168c565b89830135888111156119da5760008081fd5b6119e88e8c8387010161170e565b8252509082013590878211156119fe5760008081fd5b611a0c8d8b8486010161170e565b818b015285525050918601918601611990565b5098975050505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611aa357888303603f1901855281518051878552611a7788860182611548565b91890151858303868b0152919050611a8f8183611548565b968901969450505090860190600101611a53565b509098975050505050505050565b60008060408385031215611ac457600080fd5b825167ffffffffffffffff811115611adb57600080fd5b611ae78582860161180c565b925050602083015163ffffffff8116811461188857600080fd5b600060208284031215611b1357600080fd5b815180151581146109b657600080fd5b606081526000611b366060830186611548565b8281036020840152611b488186611548565b905082810360408401526112dd8185611548565b604081526000611b6f6040830185611548565b8281036020840152610eaf8185611548565b60008251611b93818460208701611524565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b604081526000611bc66040830185611548565b905061ffff831660208301529392505050565b606081526000611bec6060830186611548565b8281036020840152611bfe8186611548565b9150506001600160e01b031983166040830152949350505050565b600060a082016001600160a01b0388168352602060a08185015281885180845260c08601915060c08160051b8701019350828a0160005b82811015611c7e5760bf19888703018452611c6c868351611548565b95509284019290840190600101611c50565b50505050508281036040840152611c958187611548565b6001600160e01b03198616606085015290508281036080840152611cb98185611548565b98975050505050505050565b600060208284031215611cd757600080fd5b815167ffffffffffffffff811115611cee57600080fd5b6102548482850161180c565b6000815160208301516001600160e01b031980821693506004831015611d2a5780818460040360031b1b83161693505b505050919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561097757610977611d32565b8082018082111561097757610977611d32565b8051611d79816114ee565b919050565b600080600080600060a08688031215611d9657600080fd5b8551611da18161182c565b8095505060208087015167ffffffffffffffff80821115611dc157600080fd5b818901915089601f830112611dd557600080fd5b8151611de361172d826118fc565b81815260059190911b8301840190848101908c831115611e0257600080fd5b8585015b83811015611e4f57805185811115611e1e5760008081fd5b8601603f81018f13611e305760008081fd5b611e418f89830151604084016117dc565b845250918601918601611e06565b5060408c01519099509450505080831115611e6957600080fd5b611e758a848b0161180c565b9550611e8360608a01611d6e565b94506080890151925080831115611e9957600080fd5b5050611ea78882890161180c565b9150509295509295909350565b634e487b7160e01b600052600160045260246000fd5b600060018201611edc57611edc611d32565b5060010190565b600060208284031215611ef557600080fd5b81516109b68161182c565b600082611f1d57634e487b7160e01b600052601260045260246000fd5b50069056fea26469706673582212209e2b76b2a7a2481b01072a4220752eb6ab94e104ea14aab19b0274e492f0578164736f6c63430008110033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c80637dc0d1d0116100505780637dc0d1d0146101045780639061b9231461012b578063b4a858011461013e57600080fd5b806301ffc9a7146100775780633f15457f146100b057806352539968146100ef575b600080fd5b61009b610085366004611507565b6001600160e01b031916639061b92360e01b1490565b60405190151581526020015b60405180910390f35b6100d77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100a7565b6100f7610151565b6040516100a79190611574565b6100d77f000000000000000000000000000000000000000000000000000000000000000081565b6100f76101393660046115d0565b6101df565b6100f761014c3660046115d0565b61025c565b6000805461015e9061163c565b80601f016020809104026020016040519081016040528092919081815260200182805461018a9061163c565b80156101d75780601f106101ac576101008083540402835291602001916101d7565b820191906000526020600020905b8154815290600101906020018083116101ba57829003601f168201915b505050505081565b606061025485858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815292508791508690819084018382808284376000920191909152506106b792505050565b949350505050565b60606000808061026e85870187611764565b919450925090506001600160e01b031981161561031e576000808380602001905181019061029c9190611841565b91509150610312818686868e8e88306040516020016102bc929190611893565b60408051601f19818403018152908290526102db9392916024016118be565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610848565b95505050505050610254565b600061032c888a018a611920565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bdf95fef836040518263ffffffff1660e01b815260040161037c9190611a2c565b600060405180830381865afa158015610399573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103c19190810190611ab1565b50905060006103d08282610916565b90505b8051516020820151101561069b5760006103f58260000151836020015161097d565b90506104018188610998565b15806104165750606082015161ffff16600114155b8061042a5750604082015161ffff16601014155b15610435575061068d565b60008061044f84600001518560a001518660c001516109bd565b90925090506001600160a01b03821615610689576040516301ffc9a760e01b815263477cc53f60e11b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa1580156104ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d29190611b01565b1561053157610521828a8a8c8c866040516024016104f293929190611b23565b60408051601f198184030181529190526020810180516001600160e01b031663477cc53f60e11b179052610848565b9950505050505050505050610254565b6040516301ffc9a760e01b8152639061b92360e01b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa15801561057c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a09190611b01565b156105ed57610521828a8a8c8c6040516024016105be929190611b5c565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b179052610848565b600080836001600160a01b03168a6040516106089190611b81565b600060405180830381855afa9150503d8060008114610643576040519150601f19603f3d011682016040523d82523d6000602084013e610648565b606091505b50915091508115610665579a506102549950505050505050505050565b8a6040516314d3b60360e11b81526004016106809190611574565b60405180910390fd5b5050505b61069681610b05565b6103d3565b50846040516314d3b60360e11b81526004016106809190611574565b604080516001808252818301909252600091816020015b60608152602001906001900390816106ce579050509050600080546106f29061163c565b80601f016020809104026020016040519081016040528092919081815260200182805461071e9061163c565b801561076b5780601f106107405761010080835404028352916020019161076b565b820191906000526020600020905b81548152906001019060200180831161074e57829003601f168201915b50505050508160008151811061078357610783611b9d565b602002602001018190525030818460106040516024016107a4929190611bb3565b60408051601f19818403018152918152602080830180516001600160e01b03167f31b137b90000000000000000000000000000000000000000000000000000000017905290517fb4a85801000000000000000000000000000000000000000000000000000000009161081d918991899160009101611bd9565b60408051601f1981840301815290829052630556f18360e41b82526106809594939291600401611c19565b60606001600160a01b0385163b6108635761086384846106b7565b600061086f8684610bed565b90503d81156108a5576000610885600083610c7f565b90508080602001905181019061089b9190611cc5565b9350505050610254565b600481106109045760006108bb60006004610c7f565b9050630556f18360e41b6108ce82611cfa565b6001600160e01b031916036109025760006108f360046108ee8186611d48565b610c7f565b9050610900818a8a610cd4565b505b505b61090c610d65565b5050949350505050565b6109646040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261097781610b05565b92915050565b6060600061098b8484610d6f565b9050610254848483610dc9565b6000815183511480156109b657506109b68360008460008751610e4b565b9392505050565b6000606060006109ce868686610e6e565b9050600581511080610a2357506040805180820190915260058082527f454e5331200000000000000000000000000000000000000000000000000000006020830152610a21918391600091908290610e4b565b155b15610a41575050604080516020810190915260008082529150610afd565b6000610a7e6005808451610a559190611d48565b8491907f2000000000000000000000000000000000000000000000000000000000000000610eb8565b90508151811115610ab5576000610a988360058551610f54565b6040805160208101909152600081529095509350610afd92505050565b6000610ac383600584610f54565b905080610af5610ad4846001611d5b565b6001858751610ae39190611d48565b610aed9190611d48565b869190610dc9565b945094505050505b935093915050565b60c08101516020820181905281515111610b1c5750565b6000610b3082600001518360200151610d6f565b8260200151610b3f9190611d5b565b8251909150610b4e908261105e565b61ffff166040830152610b62600282611d5b565b8251909150610b71908261105e565b61ffff166060830152610b85600282611d5b565b8251909150610b949082611086565b63ffffffff166080830152610baa600482611d5b565b8251909150600090610bbc908361105e565b61ffff169050610bcd600283611d5b565b60a084018190529150610be08183611d5b565b60c0909301929092525050565b60006001600160a01b0383163b610c6c5760405162461bcd60e51b815260206004820152602e60248201527f4c6f774c6576656c43616c6c5574696c733a207374617469632063616c6c207460448201527f6f206e6f6e2d636f6e74726163740000000000000000000000000000000000006064820152608401610680565b600080835160208501865afa9392505050565b60608167ffffffffffffffff811115610c9a57610c9a611676565b6040519080825280601f01601f191660200182016040528015610cc4576020820181803683370190505b5090508183602083013e92915050565b600080600080600087806020019051810190610cf09190611d7e565b94509450945094509450866001600160a01b0316856001600160a01b031614610d45576040517f398d4d3200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b30848463b4a8580160e01b89858760405160200161081d93929190611bd9565b3d6000803e3d6000fd5b6000815b83518110610d8357610d83611eb4565b6000610d8f85836110b0565b60ff169050610d9f816001611d5b565b610da99083611d5b565b915080600003610db95750610dbf565b50610d73565b6102548382611d48565b8251606090610dd88385611d5b565b1115610de357600080fd5b60008267ffffffffffffffff811115610dfe57610dfe611676565b6040519080825280601f01601f191660200182016040528015610e28576020820181803683370190505b50905060208082019086860101610e408282876110d4565b509095945050505050565b6000610e5884848461112a565b610e6387878561112a565b149695505050505050565b60606000610e7c85856110b0565b60ff16905082610e8c8286611d5b565b10610e9957610e99611eb4565b610eaf610ea7856001611d5b565b869083610dc9565b95945050505050565b6000835b610ec68486611d5b565b811015610f4757827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916868281518110610f0257610f02611b9d565b01602001517fff000000000000000000000000000000000000000000000000000000000000001603610f35579050610254565b80610f3f81611eca565b915050610ebc565b5060001995945050505050565b6000838381518110610f6857610f68611b9d565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f3000000000000000000000000000000000000000000000000000000000000000148015611020575083610fc5846001611d5b565b81518110610fd557610fd5611b9d565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f7800000000000000000000000000000000000000000000000000000000000000145b156110535760008061103e611036866002611d5b565b87908661114e565b915091508015611050575090506109b6565b50505b61025484848461118a565b815160009061106e836002611d5b565b111561107957600080fd5b50016002015161ffff1690565b8151600090611096836004611d5b565b11156110a157600080fd5b50016004015163ffffffff1690565b60008282815181106110c4576110c4611b9d565b016020015160f81c905092915050565b6020811061110c57815183526110eb602084611d5b565b92506110f8602083611d5b565b9150611105602082611d48565b90506110d4565b905182516020929092036101000a6000190180199091169116179052565b82516000906111398385611d5b565b111561114457600080fd5b5091016020012090565b600080602861115d8585611d48565b101561116e57506000905080610afd565b60008061117c8787876112e7565b909890975095505050505050565b60008061119885858561143b565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018290529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630178b8bf90602401602060405180830381865afa15801561121c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112409190611ee3565b90506001600160a01b03811661125b576000925050506109b6565b6040517f3b3b57de000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b03821690633b3b57de90602401602060405180830381865afa1580156112b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112dd9190611ee3565b9695505050505050565b600080806112f58585611d48565b905080604014158015611309575080602814155b8061131e575061131a600282611f00565b6001145b1561136b5760405162461bcd60e51b815260206004820152601560248201527f496e76616c696420737472696e67206c656e67746800000000000000000000006044820152606401610680565b60019150855184111561137d57600080fd5b6113ce565b6000603a8210602f8311161561139a5750602f190190565b604782106040831116156113b057506036190190565b606782106060831116156113c657506056190190565b5060ff919050565b60208601855b85811015611430576113eb8183015160001a611382565b6113fd6001830184015160001a611382565b60ff811460ff8314171561141657600095505050611430565b60049190911b1760089590951b94909417936002016113d4565b505050935093915050565b6000806114788485875161144f9190611d48565b8791907f2e00000000000000000000000000000000000000000000000000000000000000610eb8565b90506000838210156114a05761149986611493846001611d5b565b8661143b565b90506114a4565b8391505b806114bb866114b38186611d48565b89919061112a565b60408051602081019390935282015260600160405160208183030381529060405280519060200120925050509392505050565b6001600160e01b03198116811461150457600080fd5b50565b60006020828403121561151957600080fd5b81356109b6816114ee565b60005b8381101561153f578181015183820152602001611527565b50506000910152565b60008151808452611560816020860160208601611524565b601f01601f19169290920160200192915050565b6020815260006109b66020830184611548565b60008083601f84011261159957600080fd5b50813567ffffffffffffffff8111156115b157600080fd5b6020830191508360208285010111156115c957600080fd5b9250929050565b600080600080604085870312156115e657600080fd5b843567ffffffffffffffff808211156115fe57600080fd5b61160a88838901611587565b9096509450602087013591508082111561162357600080fd5b5061163087828801611587565b95989497509550505050565b600181811c9082168061165057607f821691505b60208210810361167057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156116af576116af611676565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156116de576116de611676565b604052919050565b600067ffffffffffffffff82111561170057611700611676565b50601f01601f191660200190565b600082601f83011261171f57600080fd5b813561173261172d826116e6565b6116b5565b81815284602083860101111561174757600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561177957600080fd5b833567ffffffffffffffff8082111561179157600080fd5b61179d8783880161170e565b945060208601359150808211156117b357600080fd5b506117c08682870161170e565b92505060408401356117d1816114ee565b809150509250925092565b60006117ea61172d846116e6565b90508281528383830111156117fe57600080fd5b6109b6836020830184611524565b600082601f83011261181d57600080fd5b6109b6838351602085016117dc565b6001600160a01b038116811461150457600080fd5b6000806040838503121561185457600080fd5b825167ffffffffffffffff81111561186b57600080fd5b6118778582860161180c565b92505060208301516118888161182c565b809150509250929050565b6040815260006118a66040830185611548565b90506001600160a01b03831660208301529392505050565b60408152826040820152828460608301376000606084830101526000601f19601f850116820160608382030160208401526112dd6060820185611548565b600067ffffffffffffffff82111561191657611916611676565b5060051b60200190565b6000602080838503121561193357600080fd5b823567ffffffffffffffff8082111561194b57600080fd5b818501915085601f83011261195f57600080fd5b813561196d61172d826118fc565b81815260059190911b8301840190848101908883111561198c57600080fd5b8585015b83811015611a1f578035858111156119a85760008081fd5b86016040818c03601f19018113156119c05760008081fd5b6119c861168c565b89830135888111156119da5760008081fd5b6119e88e8c8387010161170e565b8252509082013590878211156119fe5760008081fd5b611a0c8d8b8486010161170e565b818b015285525050918601918601611990565b5098975050505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611aa357888303603f1901855281518051878552611a7788860182611548565b91890151858303868b0152919050611a8f8183611548565b968901969450505090860190600101611a53565b509098975050505050505050565b60008060408385031215611ac457600080fd5b825167ffffffffffffffff811115611adb57600080fd5b611ae78582860161180c565b925050602083015163ffffffff8116811461188857600080fd5b600060208284031215611b1357600080fd5b815180151581146109b657600080fd5b606081526000611b366060830186611548565b8281036020840152611b488186611548565b905082810360408401526112dd8185611548565b604081526000611b6f6040830185611548565b8281036020840152610eaf8185611548565b60008251611b93818460208701611524565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b604081526000611bc66040830185611548565b905061ffff831660208301529392505050565b606081526000611bec6060830186611548565b8281036020840152611bfe8186611548565b9150506001600160e01b031983166040830152949350505050565b600060a082016001600160a01b0388168352602060a08185015281885180845260c08601915060c08160051b8701019350828a0160005b82811015611c7e5760bf19888703018452611c6c868351611548565b95509284019290840190600101611c50565b50505050508281036040840152611c958187611548565b6001600160e01b03198616606085015290508281036080840152611cb98185611548565b98975050505050505050565b600060208284031215611cd757600080fd5b815167ffffffffffffffff811115611cee57600080fd5b6102548482850161180c565b6000815160208301516001600160e01b031980821693506004831015611d2a5780818460040360031b1b83161693505b505050919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561097757610977611d32565b8082018082111561097757610977611d32565b8051611d79816114ee565b919050565b600080600080600060a08688031215611d9657600080fd5b8551611da18161182c565b8095505060208087015167ffffffffffffffff80821115611dc157600080fd5b818901915089601f830112611dd557600080fd5b8151611de361172d826118fc565b81815260059190911b8301840190848101908c831115611e0257600080fd5b8585015b83811015611e4f57805185811115611e1e5760008081fd5b8601603f81018f13611e305760008081fd5b611e418f89830151604084016117dc565b845250918601918601611e06565b5060408c01519099509450505080831115611e6957600080fd5b611e758a848b0161180c565b9550611e8360608a01611d6e565b94506080890151925080831115611e9957600080fd5b5050611ea78882890161180c565b9150509295509295909350565b634e487b7160e01b600052600160045260246000fd5b600060018201611edc57611edc611d32565b5060010190565b600060208284031215611ef557600080fd5b81516109b68161182c565b600082611f1d57634e487b7160e01b600052601260045260246000fd5b50069056fea26469706673582212209e2b76b2a7a2481b01072a4220752eb6ab94e104ea14aab19b0274e492f0578164736f6c63430008110033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "supportsInterface(bytes4)": {
        "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas."
      }
    },
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 4878,
        "contract": "contracts/dnsregistrar/OffchainDNSResolver.sol:OffchainDNSResolver",
        "label": "gatewayURL",
        "offset": 0,
        "slot": "0",
        "type": "t_string_storage"
      }
    ],
    "types": {
      "t_string_storage": {
        "encoding": "bytes",
        "label": "string",
        "numberOfBytes": "32"
      }
    }
  }
}