{
  "address": "0xB32cB5677a7C971689228EC835800432B339bA2B",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_previousRegistrar",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_resolver",
          "type": "address"
        },
        {
          "internalType": "contract DNSSEC",
          "name": "_dnssec",
          "type": "address"
        },
        {
          "internalType": "contract PublicSuffixList",
          "name": "_suffixes",
          "type": "address"
        },
        {
          "internalType": "contract ENS",
          "name": "_ens",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "name",
          "type": "bytes"
        }
      ],
      "name": "InvalidPublicSuffix",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "NoOwnerRecordFound",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "offset",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "length",
          "type": "uint256"
        }
      ],
      "name": "OffsetOutOfBoundsError",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "caller",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        }
      ],
      "name": "PermissionDenied",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "PreconditionNotMet",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "StaleProof",
      "type": "error"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "node",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "bytes",
          "name": "dnsname",
          "type": "bytes"
        },
        {
          "indexed": false,
          "internalType": "uint32",
          "name": "inception",
          "type": "uint32"
        }
      ],
      "name": "Claim",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "suffixes",
          "type": "address"
        }
      ],
      "name": "NewPublicSuffixList",
      "type": "event"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "domain",
          "type": "bytes"
        }
      ],
      "name": "enableNode",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "node",
          "type": "bytes32"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "ens",
      "outputs": [
        {
          "internalType": "contract ENS",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "name": "inceptions",
      "outputs": [
        {
          "internalType": "uint32",
          "name": "",
          "type": "uint32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "oracle",
      "outputs": [
        {
          "internalType": "contract DNSSEC",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "previousRegistrar",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "name",
          "type": "bytes"
        },
        {
          "components": [
            {
              "internalType": "bytes",
              "name": "rrset",
              "type": "bytes"
            },
            {
              "internalType": "bytes",
              "name": "sig",
              "type": "bytes"
            }
          ],
          "internalType": "struct DNSSEC.RRSetWithSignature[]",
          "name": "input",
          "type": "tuple[]"
        }
      ],
      "name": "proveAndClaim",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "name",
          "type": "bytes"
        },
        {
          "components": [
            {
              "internalType": "bytes",
              "name": "rrset",
              "type": "bytes"
            },
            {
              "internalType": "bytes",
              "name": "sig",
              "type": "bytes"
            }
          ],
          "internalType": "struct DNSSEC.RRSetWithSignature[]",
          "name": "input",
          "type": "tuple[]"
        },
        {
          "internalType": "address",
          "name": "resolver",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "addr",
          "type": "address"
        }
      ],
      "name": "proveAndClaimWithResolver",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "resolver",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract PublicSuffixList",
          "name": "_suffixes",
          "type": "address"
        }
      ],
      "name": "setPublicSuffixList",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "suffixes",
      "outputs": [
        {
          "internalType": "contract PublicSuffixList",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes4",
          "name": "interfaceID",
          "type": "bytes4"
        }
      ],
      "name": "supportsInterface",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "pure",
      "type": "function"
    }
  ],
  "transactionHash": "0x5ddb98103acbe8b5a68ac1b7e45abbddda5dff8ff2b65c5ed26e36cf34bec43e",
  "receipt": {
    "to": null,
    "from": "0x0904Dac3347eA47d208F3Fd67402D039a3b99859",
    "contractAddress": "0xB32cB5677a7C971689228EC835800432B339bA2B",
    "transactionIndex": 32,
    "gasUsed": "1957892",
    "logsBloom": "0x00080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x68fbaf4525e996d170cc181078aae224e20e0729313fdc879f53409a20572b74",
    "transactionHash": "0x5ddb98103acbe8b5a68ac1b7e45abbddda5dff8ff2b65c5ed26e36cf34bec43e",
    "logs": [
      {
        "transactionIndex": 32,
        "blockNumber": 19027588,
        "transactionHash": "0x5ddb98103acbe8b5a68ac1b7e45abbddda5dff8ff2b65c5ed26e36cf34bec43e",
        "address": "0xB32cB5677a7C971689228EC835800432B339bA2B",
        "topics": [
          "0x9176b7f47e4504df5e5516c99d90d82ac7cbd49cc77e7f22ba2ac2f2e3a3eba8"
        ],
        "data": "0x000000000000000000000000823bda9ca8c47d072376ecd595530c8fb2faa3ed",
        "logIndex": 104,
        "blockHash": "0x68fbaf4525e996d170cc181078aae224e20e0729313fdc879f53409a20572b74"
      }
    ],
    "blockNumber": 19027588,
    "cumulativeGasUsed": "5118017",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0x58774bb8acd458a640af0b88238369a167546ef2",
    "0xF142B308cF687d4358410a4cB885513b30A42025",
    "0x0fc3152971714E5ed7723FAFa650F86A4BaF30C5",
    "0x823BDa9cA8c47d072376eCD595530c8fb2fAa3ED",
    "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
  ],
  "numDeployments": 7,
  "solcInputHash": "a57ee6145a733d774c1e1946fd5c16b8",
  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_previousRegistrar\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_resolver\",\"type\":\"address\"},{\"internalType\":\"contract DNSSEC\",\"name\":\"_dnssec\",\"type\":\"address\"},{\"internalType\":\"contract PublicSuffixList\",\"name\":\"_suffixes\",\"type\":\"address\"},{\"internalType\":\"contract ENS\",\"name\":\"_ens\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"InvalidPublicSuffix\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoOwnerRecordFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"PermissionDenied\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PreconditionNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleProof\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"dnsname\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"inception\",\"type\":\"uint32\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"suffixes\",\"type\":\"address\"}],\"name\":\"NewPublicSuffixList\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"domain\",\"type\":\"bytes\"}],\"name\":\"enableNode\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ens\",\"outputs\":[{\"internalType\":\"contract ENS\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"inceptions\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract DNSSEC\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousRegistrar\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature[]\",\"name\":\"input\",\"type\":\"tuple[]\"}],\"name\":\"proveAndClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature[]\",\"name\":\"input\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"proveAndClaimWithResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract PublicSuffixList\",\"name\":\"_suffixes\",\"type\":\"address\"}],\"name\":\"setPublicSuffixList\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"suffixes\",\"outputs\":[{\"internalType\":\"contract PublicSuffixList\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"An ENS registrar that allows the owner of a DNS name to claim the      corresponding name in ENS.\",\"kind\":\"dev\",\"methods\":{\"proveAndClaim(bytes,(bytes,bytes)[])\":{\"details\":\"Submits proofs to the DNSSEC oracle, then claims a name using those proofs.\",\"params\":{\"input\":\"A chain of signed DNS RRSETs ending with a text record.\",\"name\":\"The name to claim, in DNS wire format.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnsregistrar/DNSRegistrar.sol\":\"DNSRegistrar\"},\"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/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n    address private _owner;\\n\\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n    /**\\n     * @dev Initializes the contract setting the deployer as the initial owner.\\n     */\\n    constructor() {\\n        _transferOwnership(_msgSender());\\n    }\\n\\n    /**\\n     * @dev Throws if called by any account other than the owner.\\n     */\\n    modifier onlyOwner() {\\n        _checkOwner();\\n        _;\\n    }\\n\\n    /**\\n     * @dev Returns the address of the current owner.\\n     */\\n    function owner() public view virtual returns (address) {\\n        return _owner;\\n    }\\n\\n    /**\\n     * @dev Throws if the sender is not the owner.\\n     */\\n    function _checkOwner() internal view virtual {\\n        require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n    }\\n\\n    /**\\n     * @dev Leaves the contract without owner. It will not be possible to call\\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\\n     *\\n     * NOTE: Renouncing ownership will leave the contract without an owner,\\n     * thereby removing any functionality that is only available to the owner.\\n     */\\n    function renounceOwnership() public virtual onlyOwner {\\n        _transferOwnership(address(0));\\n    }\\n\\n    /**\\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n     * Can only be called by the current owner.\\n     */\\n    function transferOwnership(address newOwner) public virtual onlyOwner {\\n        require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n        _transferOwnership(newOwner);\\n    }\\n\\n    /**\\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n     * Internal function without access restriction.\\n     */\\n    function _transferOwnership(address newOwner) internal virtual {\\n        address oldOwner = _owner;\\n        _owner = newOwner;\\n        emit OwnershipTransferred(oldOwner, newOwner);\\n    }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n    function _msgSender() internal view virtual returns (address) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes calldata) {\\n        return msg.data;\\n    }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"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/DNSClaimChecker.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../dnssec-oracle/DNSSEC.sol\\\";\\nimport \\\"../dnssec-oracle/BytesUtils.sol\\\";\\nimport \\\"../dnssec-oracle/RRUtils.sol\\\";\\nimport \\\"../utils/HexUtils.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\nlibrary DNSClaimChecker {\\n    using BytesUtils for bytes;\\n    using HexUtils for bytes;\\n    using RRUtils for *;\\n    using Buffer for Buffer.buffer;\\n\\n    uint16 constant CLASS_INET = 1;\\n    uint16 constant TYPE_TXT = 16;\\n\\n    function getOwnerAddress(\\n        bytes memory name,\\n        bytes memory data\\n    ) internal pure returns (address, bool) {\\n        // Add \\\"_ens.\\\" to the front of the name.\\n        Buffer.buffer memory buf;\\n        buf.init(name.length + 5);\\n        buf.append(\\\"\\\\x04_ens\\\");\\n        buf.append(name);\\n\\n        for (\\n            RRUtils.RRIterator memory iter = data.iterateRRs(0);\\n            !iter.done();\\n            iter.next()\\n        ) {\\n            if (iter.name().compareNames(buf.buf) != 0) continue;\\n            bool found;\\n            address addr;\\n            (addr, found) = parseRR(data, iter.rdataOffset, iter.nextOffset);\\n            if (found) {\\n                return (addr, true);\\n            }\\n        }\\n\\n        return (address(0x0), false);\\n    }\\n\\n    function parseRR(\\n        bytes memory rdata,\\n        uint256 idx,\\n        uint256 endIdx\\n    ) internal pure returns (address, bool) {\\n        while (idx < endIdx) {\\n            uint256 len = rdata.readUint8(idx);\\n            idx += 1;\\n\\n            bool found;\\n            address addr;\\n            (addr, found) = parseString(rdata, idx, len);\\n\\n            if (found) return (addr, true);\\n            idx += len;\\n        }\\n\\n        return (address(0x0), false);\\n    }\\n\\n    function parseString(\\n        bytes memory str,\\n        uint256 idx,\\n        uint256 len\\n    ) internal pure returns (address, bool) {\\n        // TODO: More robust parsing that handles whitespace and multiple key/value pairs\\n        if (str.readUint32(idx) != 0x613d3078) return (address(0x0), false); // 0x613d3078 == 'a=0x'\\n        return str.hexToAddress(idx + 4, idx + len);\\n    }\\n}\\n\",\"keccak256\":\"0x8269236f2a421e278e3e9642d2a5c29545993e8a4586a2592067155822d59069\",\"license\":\"MIT\"},\"contracts/dnsregistrar/DNSRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\nimport \\\"../dnssec-oracle/BytesUtils.sol\\\";\\nimport \\\"../dnssec-oracle/DNSSEC.sol\\\";\\nimport \\\"../dnssec-oracle/RRUtils.sol\\\";\\nimport \\\"../registry/ENSRegistry.sol\\\";\\nimport \\\"../root/Root.sol\\\";\\nimport \\\"../resolvers/profiles/AddrResolver.sol\\\";\\nimport \\\"./DNSClaimChecker.sol\\\";\\nimport \\\"./PublicSuffixList.sol\\\";\\nimport \\\"./IDNSRegistrar.sol\\\";\\n\\n/**\\n * @dev An ENS registrar that allows the owner of a DNS name to claim the\\n *      corresponding name in ENS.\\n */\\ncontract DNSRegistrar is IDNSRegistrar, IERC165 {\\n    using BytesUtils for bytes;\\n    using Buffer for Buffer.buffer;\\n    using RRUtils for *;\\n\\n    ENS public immutable ens;\\n    DNSSEC public immutable oracle;\\n    PublicSuffixList public suffixes;\\n    address public immutable previousRegistrar;\\n    address public immutable resolver;\\n    // A mapping of the most recent signatures seen for each claimed domain.\\n    mapping(bytes32 => uint32) public inceptions;\\n\\n    error NoOwnerRecordFound();\\n    error PermissionDenied(address caller, address owner);\\n    error PreconditionNotMet();\\n    error StaleProof();\\n    error InvalidPublicSuffix(bytes name);\\n\\n    struct OwnerRecord {\\n        bytes name;\\n        address owner;\\n        address resolver;\\n        uint64 ttl;\\n    }\\n\\n    event Claim(\\n        bytes32 indexed node,\\n        address indexed owner,\\n        bytes dnsname,\\n        uint32 inception\\n    );\\n    event NewPublicSuffixList(address suffixes);\\n\\n    constructor(\\n        address _previousRegistrar,\\n        address _resolver,\\n        DNSSEC _dnssec,\\n        PublicSuffixList _suffixes,\\n        ENS _ens\\n    ) {\\n        previousRegistrar = _previousRegistrar;\\n        resolver = _resolver;\\n        oracle = _dnssec;\\n        suffixes = _suffixes;\\n        emit NewPublicSuffixList(address(suffixes));\\n        ens = _ens;\\n    }\\n\\n    /**\\n     * @dev This contract's owner-only functions can be invoked by the owner of the ENS root.\\n     */\\n    modifier onlyOwner() {\\n        Root root = Root(ens.owner(bytes32(0)));\\n        address owner = root.owner();\\n        require(msg.sender == owner);\\n        _;\\n    }\\n\\n    function setPublicSuffixList(PublicSuffixList _suffixes) public onlyOwner {\\n        suffixes = _suffixes;\\n        emit NewPublicSuffixList(address(suffixes));\\n    }\\n\\n    /**\\n     * @dev Submits proofs to the DNSSEC oracle, then claims a name using those proofs.\\n     * @param name The name to claim, in DNS wire format.\\n     * @param input A chain of signed DNS RRSETs ending with a text record.\\n     */\\n    function proveAndClaim(\\n        bytes memory name,\\n        DNSSEC.RRSetWithSignature[] memory input\\n    ) public override {\\n        (bytes32 rootNode, bytes32 labelHash, address addr) = _claim(\\n            name,\\n            input\\n        );\\n        ens.setSubnodeOwner(rootNode, labelHash, addr);\\n    }\\n\\n    function proveAndClaimWithResolver(\\n        bytes memory name,\\n        DNSSEC.RRSetWithSignature[] memory input,\\n        address resolver,\\n        address addr\\n    ) public override {\\n        (bytes32 rootNode, bytes32 labelHash, address owner) = _claim(\\n            name,\\n            input\\n        );\\n        if (msg.sender != owner) {\\n            revert PermissionDenied(msg.sender, owner);\\n        }\\n        ens.setSubnodeRecord(rootNode, labelHash, owner, resolver, 0);\\n        if (addr != address(0)) {\\n            if (resolver == address(0)) {\\n                revert PreconditionNotMet();\\n            }\\n            bytes32 node = keccak256(abi.encodePacked(rootNode, labelHash));\\n            // Set the resolver record\\n            AddrResolver(resolver).setAddr(node, addr);\\n        }\\n    }\\n\\n    function supportsInterface(\\n        bytes4 interfaceID\\n    ) external pure override returns (bool) {\\n        return\\n            interfaceID == type(IERC165).interfaceId ||\\n            interfaceID == type(IDNSRegistrar).interfaceId;\\n    }\\n\\n    function _claim(\\n        bytes memory name,\\n        DNSSEC.RRSetWithSignature[] memory input\\n    ) internal returns (bytes32 parentNode, bytes32 labelHash, address addr) {\\n        (bytes memory data, uint32 inception) = oracle.verifyRRSet(input);\\n\\n        // Get the first label\\n        uint256 labelLen = name.readUint8(0);\\n        labelHash = name.keccak(1, labelLen);\\n\\n        bytes memory parentName = name.substring(\\n            labelLen + 1,\\n            name.length - labelLen - 1\\n        );\\n\\n        // Make sure the parent name is enabled\\n        parentNode = enableNode(parentName);\\n\\n        bytes32 node = keccak256(abi.encodePacked(parentNode, labelHash));\\n        if (!RRUtils.serialNumberGte(inception, inceptions[node])) {\\n            revert StaleProof();\\n        }\\n        inceptions[node] = inception;\\n\\n        bool found;\\n        (addr, found) = DNSClaimChecker.getOwnerAddress(name, data);\\n        if (!found) {\\n            revert NoOwnerRecordFound();\\n        }\\n\\n        emit Claim(node, addr, name, inception);\\n    }\\n\\n    function enableNode(bytes memory domain) public returns (bytes32 node) {\\n        // Name must be in the public suffix list.\\n        if (!suffixes.isPublicSuffix(domain)) {\\n            revert InvalidPublicSuffix(domain);\\n        }\\n        return _enableNode(domain, 0);\\n    }\\n\\n    function _enableNode(\\n        bytes memory domain,\\n        uint256 offset\\n    ) internal returns (bytes32 node) {\\n        uint256 len = domain.readUint8(offset);\\n        if (len == 0) {\\n            return bytes32(0);\\n        }\\n\\n        bytes32 parentNode = _enableNode(domain, offset + len + 1);\\n        bytes32 label = domain.keccak(offset + 1, len);\\n        node = keccak256(abi.encodePacked(parentNode, label));\\n        address owner = ens.owner(node);\\n        if (owner == address(0) || owner == previousRegistrar) {\\n            if (parentNode == bytes32(0)) {\\n                Root root = Root(ens.owner(bytes32(0)));\\n                root.setSubnodeOwner(label, address(this));\\n                ens.setResolver(node, resolver);\\n            } else {\\n                ens.setSubnodeRecord(\\n                    parentNode,\\n                    label,\\n                    address(this),\\n                    resolver,\\n                    0\\n                );\\n            }\\n        } else if (owner != address(this)) {\\n            revert PreconditionNotMet();\\n        }\\n        return node;\\n    }\\n}\\n\",\"keccak256\":\"0x9140c28eee7f8dff1cc0a2380e9b57db3203c8c0d187245ab3595f4e4cbdebce\",\"license\":\"MIT\"},\"contracts/dnsregistrar/IDNSRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../dnssec-oracle/DNSSEC.sol\\\";\\n\\ninterface IDNSRegistrar {\\n    function proveAndClaim(\\n        bytes memory name,\\n        DNSSEC.RRSetWithSignature[] memory input\\n    ) external;\\n\\n    function proveAndClaimWithResolver(\\n        bytes memory name,\\n        DNSSEC.RRSetWithSignature[] memory input,\\n        address resolver,\\n        address addr\\n    ) external;\\n}\\n\",\"keccak256\":\"0xcf6607fe4918cabb1c4c2130597dd9cc0f63492564b05de60496eb46873a73b7\",\"license\":\"MIT\"},\"contracts/dnsregistrar/PublicSuffixList.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\ninterface PublicSuffixList {\\n    function isPublicSuffix(bytes calldata name) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x12158ba8838ee2b1ebb0178a52d2f4d54dcc68282d569226e62afc2b0dccbbac\"},\"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/ResolverBase.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"./profiles/IVersionableResolver.sol\\\";\\n\\nabstract contract ResolverBase is ERC165, IVersionableResolver {\\n    mapping(bytes32 => uint64) public recordVersions;\\n\\n    function isAuthorised(bytes32 node) internal view virtual returns (bool);\\n\\n    modifier authorised(bytes32 node) {\\n        require(isAuthorised(node));\\n        _;\\n    }\\n\\n    /**\\n     * Increments the record version associated with an ENS node.\\n     * May only be called by the owner of that node in the ENS registry.\\n     * @param node The node to update.\\n     */\\n    function clearRecords(bytes32 node) public virtual authorised(node) {\\n        recordVersions[node]++;\\n        emit VersionChanged(node, recordVersions[node]);\\n    }\\n\\n    function supportsInterface(\\n        bytes4 interfaceID\\n    ) public view virtual override returns (bool) {\\n        return\\n            interfaceID == type(IVersionableResolver).interfaceId ||\\n            super.supportsInterface(interfaceID);\\n    }\\n}\\n\",\"keccak256\":\"0x893049fffd6feee06d7acef1680f6e26505bedff62a9f7a17e921c0ba2f66307\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/AddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./IAddrResolver.sol\\\";\\nimport \\\"./IAddressResolver.sol\\\";\\n\\nabstract contract AddrResolver is\\n    IAddrResolver,\\n    IAddressResolver,\\n    ResolverBase\\n{\\n    uint256 private constant COIN_TYPE_ETH = 60;\\n\\n    mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_addresses;\\n\\n    /**\\n     * Sets the address associated with an ENS node.\\n     * May only be called by the owner of that node in the ENS registry.\\n     * @param node The node to update.\\n     * @param a The address to set.\\n     */\\n    function setAddr(\\n        bytes32 node,\\n        address a\\n    ) external virtual authorised(node) {\\n        setAddr(node, COIN_TYPE_ETH, addressToBytes(a));\\n    }\\n\\n    /**\\n     * Returns the address associated with an ENS node.\\n     * @param node The ENS node to query.\\n     * @return The associated address.\\n     */\\n    function addr(\\n        bytes32 node\\n    ) public view virtual override returns (address payable) {\\n        bytes memory a = addr(node, COIN_TYPE_ETH);\\n        if (a.length == 0) {\\n            return payable(0);\\n        }\\n        return bytesToAddress(a);\\n    }\\n\\n    function setAddr(\\n        bytes32 node,\\n        uint256 coinType,\\n        bytes memory a\\n    ) public virtual authorised(node) {\\n        emit AddressChanged(node, coinType, a);\\n        if (coinType == COIN_TYPE_ETH) {\\n            emit AddrChanged(node, bytesToAddress(a));\\n        }\\n        versionable_addresses[recordVersions[node]][node][coinType] = a;\\n    }\\n\\n    function addr(\\n        bytes32 node,\\n        uint256 coinType\\n    ) public view virtual override returns (bytes memory) {\\n        return versionable_addresses[recordVersions[node]][node][coinType];\\n    }\\n\\n    function supportsInterface(\\n        bytes4 interfaceID\\n    ) public view virtual override returns (bool) {\\n        return\\n            interfaceID == type(IAddrResolver).interfaceId ||\\n            interfaceID == type(IAddressResolver).interfaceId ||\\n            super.supportsInterface(interfaceID);\\n    }\\n\\n    function bytesToAddress(\\n        bytes memory b\\n    ) internal pure returns (address payable a) {\\n        require(b.length == 20);\\n        assembly {\\n            a := div(mload(add(b, 32)), exp(256, 12))\\n        }\\n    }\\n\\n    function addressToBytes(address a) internal pure returns (bytes memory b) {\\n        b = new bytes(20);\\n        assembly {\\n            mstore(add(b, 32), mul(a, exp(256, 12)))\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x7f6ebb3144530a02db03379f33ade869c8408eceed36dfbd751aaff198735b55\",\"license\":\"MIT\"},\"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/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/**\\n * Interface for the new (multicoin) addr function.\\n */\\ninterface IAddressResolver {\\n    event AddressChanged(\\n        bytes32 indexed node,\\n        uint256 coinType,\\n        bytes newAddress\\n    );\\n\\n    function addr(\\n        bytes32 node,\\n        uint256 coinType\\n    ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x411447c1e90c51e09702815a85ec725ffbbe37cf96e8cc4d2a8bd4ad8a59d73e\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IVersionableResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IVersionableResolver {\\n    event VersionChanged(bytes32 indexed node, uint64 newVersion);\\n\\n    function recordVersions(bytes32 node) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0xd0d09596f20c57bafb2ffa8521a8c57120e9af6c6b194f9c689d4da56f91a57c\",\"license\":\"MIT\"},\"contracts/root/Controllable.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract Controllable is Ownable {\\n    mapping(address => bool) public controllers;\\n\\n    event ControllerChanged(address indexed controller, bool enabled);\\n\\n    modifier onlyController() {\\n        require(\\n            controllers[msg.sender],\\n            \\\"Controllable: Caller is not a controller\\\"\\n        );\\n        _;\\n    }\\n\\n    function setController(address controller, bool enabled) public onlyOwner {\\n        controllers[controller] = enabled;\\n        emit ControllerChanged(controller, enabled);\\n    }\\n}\\n\",\"keccak256\":\"0xb19b8c0fafe9ca2b4bf8aaafee486fa31437672e1e1977bdf84bfe03464969db\"},\"contracts/root/Root.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"./Controllable.sol\\\";\\n\\ncontract Root is Ownable, Controllable {\\n    bytes32 private constant ROOT_NODE = bytes32(0);\\n\\n    bytes4 private constant INTERFACE_META_ID =\\n        bytes4(keccak256(\\\"supportsInterface(bytes4)\\\"));\\n\\n    event TLDLocked(bytes32 indexed label);\\n\\n    ENS public ens;\\n    mapping(bytes32 => bool) public locked;\\n\\n    constructor(ENS _ens) public {\\n        ens = _ens;\\n    }\\n\\n    function setSubnodeOwner(\\n        bytes32 label,\\n        address owner\\n    ) external onlyController {\\n        require(!locked[label]);\\n        ens.setSubnodeOwner(ROOT_NODE, label, owner);\\n    }\\n\\n    function setResolver(address resolver) external onlyOwner {\\n        ens.setResolver(ROOT_NODE, resolver);\\n    }\\n\\n    function lock(bytes32 label) external onlyOwner {\\n        emit TLDLocked(label);\\n        locked[label] = true;\\n    }\\n\\n    function supportsInterface(\\n        bytes4 interfaceID\\n    ) external pure returns (bool) {\\n        return interfaceID == INTERFACE_META_ID;\\n    }\\n}\\n\",\"keccak256\":\"0x469b281e1a9e1c3dad9c860a4ab3a7299a48355b0b0243713e0829193c39f50c\"},\"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\"}},\"version\":1}",
  "bytecode": "0x6101006040523480156200001257600080fd5b50604051620023e1380380620023e18339810160408190526200003591620000c8565b6001600160a01b0385811660c05284811660e05283811660a052600080546001600160a01b03191691841691821790556040519081527f9176b7f47e4504df5e5516c99d90d82ac7cbd49cc77e7f22ba2ac2f2e3a3eba89060200160405180910390a16001600160a01b0316608052506200014892505050565b6001600160a01b0381168114620000c557600080fd5b50565b600080600080600060a08688031215620000e157600080fd5b8551620000ee81620000af565b60208701519095506200010181620000af565b60408701519094506200011481620000af565b60608701519093506200012781620000af565b60808701519092506200013a81620000af565b809150509295509295909350565b60805160a05160c05160e051612213620001ce6000396000818160fb01528181610cde0152610d950152600081816102320152610b6301526000818161020b01526108020152600081816101c301528181610397015281816104f8015281816106b301528181610ae301528181610bba01528181610d060152610dc401526122136000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c806329d56630116100815780636f9512211161005b5780636f951221146101e55780637dc0d1d014610206578063ab14ec591461022d57600080fd5b806329d566301461019857806330349ebe146101ab5780633f15457f146101be57600080fd5b806306963218116100b257806306963218146101355780631ecfc4111461014a57806325916d411461015d57600080fd5b806301ffc9a7146100ce57806304f3bcec146100f6575b600080fd5b6100e16100dc366004611a75565b610254565b60405190151581526020015b60405180910390f35b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100ed565b610148610143366004611cb7565b6102ed565b005b610148610158366004611d40565b6104df565b61018361016b366004611d5d565b60016020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016100ed565b6101486101a6366004611d76565b610656565b60005461011d906001600160a01b031681565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b6101f86101f3366004611dda565b61072a565b6040519081526020016100ed565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102e757507fffffffff0000000000000000000000000000000000000000000000000000000082167f2f43542800000000000000000000000000000000000000000000000000000000145b92915050565b60008060006102fc87876107f8565b91945092509050336001600160a01b0382161461035b576040517fe03f60240000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03821660248201526044015b60405180910390fd5b6040516305ef2c7f60e41b815260048101849052602481018390526001600160a01b0382811660448301528681166064830152600060848301527f00000000000000000000000000000000000000000000000000000000000000001690635ef2c7f09060a401600060405180830381600087803b1580156103db57600080fd5b505af11580156103ef573d6000803e3d6000fd5b505050506001600160a01b038416156104d6576001600160a01b03851661042957604051633c584f1360e21b815260040160405180910390fd5b604080516020810185905290810183905260009060600160408051808303601f190181529082905280516020909101207fd5fa2b00000000000000000000000000000000000000000000000000000000008252600482018190526001600160a01b03878116602484015290925087169063d5fa2b0090604401600060405180830381600087803b1580156104bc57600080fd5b505af11580156104d0573d6000803e3d6000fd5b50505050505b50505050505050565b6040516302571be360e01b8152600060048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015610547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056b9190611e0f565b90506000816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d19190611e0f565b9050336001600160a01b038216146105e857600080fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0385169081179091556040519081527f9176b7f47e4504df5e5516c99d90d82ac7cbd49cc77e7f22ba2ac2f2e3a3eba89060200160405180910390a1505050565b600080600061066585856107f8565b6040517f06ab592300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b03828116604483015293965091945092507f0000000000000000000000000000000000000000000000000000000000000000909116906306ab5923906064016020604051808303816000875af11580156106fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107229190611e2c565b505050505050565b600080546040517f4f89059e0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690634f89059e90610774908590600401611e95565b602060405180830381865afa158015610791573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b59190611ea8565b6107ed57816040517f396e24b80000000000000000000000000000000000000000000000000000000081526004016103529190611e95565b6102e7826000610a35565b60008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bdf95fef876040518263ffffffff1660e01b815260040161084c9190611eca565b600060405180830381865afa158015610869573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108919190810190611f4f565b909250905060006108a28882610e58565b60ff1690506108b388600183610e7c565b945060006108e66108c5836001611ffc565b6001848c516108d4919061200f565b6108de919061200f565b8b9190610ea0565b90506108f18161072a565b965060008787604051602001610911929190918252602082015260400190565b60408051808303601f190181529181528151602092830120600081815260019093529082205490925063ffffffff16850360030b121561097d576040517f2dd6a7af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260408120805463ffffffff191663ffffffff87161790556109a88b87610f22565b9097509050806109e4576040517f6260f6f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b866001600160a01b0316827f87db02a0e483e2818060eddcbb3488ce44e35aff49a70d92c2aa6c8046cf01e28d88604051610a20929190612022565b60405180910390a35050505050509250925092565b600080610a428484610e58565b60ff16905080600003610a595750600090506102e7565b6000610a7985610a698487611ffc565b610a74906001611ffc565b610a35565b90506000610a93610a8b866001611ffc565b879085610e7c565b604080516020810185905290810182905290915060600160408051601f198184030181529082905280516020909101206302571be360e01b82526004820181905294506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906302571be390602401602060405180830381865afa158015610b2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4e9190611e0f565b90506001600160a01b0381161580610b9757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316145b15610e255782610d6a576040516302571be360e01b8152600060048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d9190611e0f565b6040517f8cb8ecec000000000000000000000000000000000000000000000000000000008152600481018590523060248201529091506001600160a01b03821690638cb8ecec90604401600060405180830381600087803b158015610c9157600080fd5b505af1158015610ca5573d6000803e3d6000fd5b50506040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018990526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000169250631896f70a9150604401600060405180830381600087803b158015610d4c57600080fd5b505af1158015610d60573d6000803e3d6000fd5b5050505050610e4e565b6040516305ef2c7f60e41b815260048101849052602481018390523060448201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166064830152600060848301527f00000000000000000000000000000000000000000000000000000000000000001690635ef2c7f09060a401600060405180830381600087803b158015610e0857600080fd5b505af1158015610e1c573d6000803e3d6000fd5b50505050610e4e565b6001600160a01b0381163014610e4e57604051633c584f1360e21b815260040160405180910390fd5b5050505092915050565b6000828281518110610e6c57610e6c61204a565b016020015160f81c905092915050565b8251600090610e8b8385611ffc565b1115610e9657600080fd5b5091016020012090565b8251606090610eaf8385611ffc565b1115610eba57600080fd5b60008267ffffffffffffffff811115610ed557610ed5611ab7565b6040519080825280601f01601f191660200182016040528015610eff576020820181803683370190505b50905060208082019086860101610f17828287611030565b509095945050505050565b600080610f42604051806040016040528060608152602001600081525090565b610f5a85516005610f539190611ffc565b8290611086565b5060408051808201909152600581527f045f656e730000000000000000000000000000000000000000000000000000006020820152610f9a9082906110fd565b50610fa581866110fd565b506000610fb28582611125565b90505b8051516020820151101561101f578151610fd890610fd283611186565b906111a7565b60000361101157600080610ff5878460a001518560c00151611300565b92509050811561100e5794506001935061102992505050565b50505b61101a81611373565b610fb5565b5060008092509250505b9250929050565b602081106110685781518352611047602084611ffc565b9250611054602083611ffc565b915061106160208261200f565b9050611030565b905182516020929092036101000a6000190180199091169116179052565b6040805180820190915260608152600060208201526110a6602083612060565b156110ce576110b6602083612060565b6110c190602061200f565b6110cb9083611ffc565b91505b6020808401839052604051808552600081529081840101818110156110f257600080fd5b604052509192915050565b60408051808201909152606081526000602082015261111e8383845161145b565b9392505050565b6111736040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c081018290526102e781611373565b602081015181516060916102e79161119e9082611531565b84519190610ea0565b60006111b38383611593565b156111c0575060006102e7565b60008060008060006111d38860006115b1565b905060006111e28860006115b1565b90505b8082111561120e578593506111fa898761160e565b95508161120681612082565b9250506111e5565b8181111561123757849250611223888661160e565b94508061122f81612082565b91505061120e565b600082118015611250575061124e89878a88611632565b155b1561128557859350611262898761160e565b9550849250611271888661160e565b945061127e60018361200f565b9150611237565b8560000361129d5760001996505050505050506102e7565b846000036112b457600196505050505050506102e7565b6112f36112c2856001611ffc565b6112cc8b87610e58565b60ff168a6112db876001611ffc565b6112e58d89610e58565b8e949392919060ff16611667565b9998505050505050505050565b6000805b828410156113645760006113188686610e58565b60ff169050611328600186611ffc565b94506000806113388888856117e5565b9250905081156113505793506001925061136b915050565b61135a8388611ffc565b9650505050611304565b5060009050805b935093915050565b60c0810151602082018190528151511161138a5750565b600061139e82600001518360200151611531565b82602001516113ad9190611ffc565b82519091506113bc9082611839565b61ffff1660408301526113d0600282611ffc565b82519091506113df9082611839565b61ffff1660608301526113f3600282611ffc565b82519091506114029082611861565b63ffffffff166080830152611418600482611ffc565b825190915060009061142a9083611839565b61ffff16905061143b600283611ffc565b60a08401819052915061144e8183611ffc565b60c0909301929092525050565b604080518082019091526060815260006020820152825182111561147e57600080fd5b835151600061148d8483611ffc565b905085602001518111156114af576114af866114aa836002612099565b61188b565b8551805183820160200191600091808511156114c9578482525b505050602086015b6020861061150957805182526114e8602083611ffc565b91506114f5602082611ffc565b905061150260208761200f565b95506114d1565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b6000815b83518110611545576115456120b0565b60006115518583610e58565b60ff169050611561816001611ffc565b61156b9083611ffc565b91508060000361157b5750611581565b50611535565b61158b838261200f565b949350505050565b60008151835114801561111e575061111e83600084600087516118a8565b6000805b835183106115c5576115c56120b0565b60006115d18585610e58565b60ff1690506115e1816001611ffc565b6115eb9085611ffc565b9350806000036115fb575061111e565b611606600183611ffc565b9150506115b5565b600061161a8383610e58565b60ff16611628836001611ffc565b61111e9190611ffc565b600061164b8383848651611646919061200f565b610e7c565b61165d8686878951611646919061200f565b1495945050505050565b85516000906116768688611ffc565b11156116aa576116868587611ffc565b8751604051638a3c1cfb60e01b815260048101929092526024820152604401610352565b83516116b68385611ffc565b11156116ea576116c68284611ffc565b8451604051638a3c1cfb60e01b815260048101929092526024820152604401610352565b84808310156116f65750815b60208789018101908587010160005b838110156117ca578251825180821461179a5760006020611726858961200f565b106117345750600019611770565b600187611742866020611ffc565b61174c919061200f565b611757906008612099565b6117629060026121aa565b61176c919061200f565b1990505b60006117808383168584166121b6565b905080156117975797506117db9650505050505050565b50505b6117a5602086611ffc565b94506117b2602085611ffc565b935050506020816117c39190611ffc565b9050611705565b506117d585896121b6565b93505050505b9695505050505050565b6000806117f28585611861565b63ffffffff1663613d30781461180d5750600090508061136b565b61182d61181b856004611ffc565b6118258587611ffc565b8791906118cb565b91509150935093915050565b8151600090611849836002611ffc565b111561185457600080fd5b50016002015161ffff1690565b8151600090611871836004611ffc565b111561187c57600080fd5b50016004015163ffffffff1690565b81516118978383611086565b506118a283826110fd565b50505050565b60006118b5848484610e7c565b6118c0878785610e7c565b149695505050505050565b60008060286118da858561200f565b10156118eb5750600090508061136b565b6000806118f9878787611907565b909890975095505050505050565b60008080611915858561200f565b905080604014158015611929575080602814155b8061193e575061193a600282612060565b6001145b156119a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c696420737472696e67206c656e67746800000000000000000000006044820152606401610352565b6001915085518411156119b757600080fd5b611a08565b6000603a8210602f831116156119d45750602f190190565b604782106040831116156119ea57506036190190565b60678210606083111615611a0057506056190190565b5060ff919050565b60208601855b85811015611a6a57611a258183015160001a6119bc565b611a376001830184015160001a6119bc565b60ff811460ff83141715611a5057600095505050611a6a565b60049190911b1760089590951b9490941793600201611a0e565b505050935093915050565b600060208284031215611a8757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461111e57600080fd5b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611af057611af0611ab7565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611b1f57611b1f611ab7565b604052919050565b600067ffffffffffffffff821115611b4157611b41611ab7565b50601f01601f191660200190565b600082601f830112611b6057600080fd5b8135611b73611b6e82611b27565b611af6565b818152846020838601011115611b8857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112611bb657600080fd5b8135602067ffffffffffffffff80831115611bd357611bd3611ab7565b8260051b611be2838201611af6565b9384528581018301938381019088861115611bfc57600080fd5b84880192505b85831015611c9357823584811115611c1a5760008081fd5b88016040818b03601f1901811315611c325760008081fd5b611c3a611acd565b8783013587811115611c4c5760008081fd5b611c5a8d8a83870101611b4f565b825250908201359086821115611c705760008081fd5b611c7e8c8984860101611b4f565b81890152845250509184019190840190611c02565b98975050505050505050565b6001600160a01b0381168114611cb457600080fd5b50565b60008060008060808587031215611ccd57600080fd5b843567ffffffffffffffff80821115611ce557600080fd5b611cf188838901611b4f565b95506020870135915080821115611d0757600080fd5b50611d1487828801611ba5565b9350506040850135611d2581611c9f565b91506060850135611d3581611c9f565b939692955090935050565b600060208284031215611d5257600080fd5b813561111e81611c9f565b600060208284031215611d6f57600080fd5b5035919050565b60008060408385031215611d8957600080fd5b823567ffffffffffffffff80821115611da157600080fd5b611dad86838701611b4f565b93506020850135915080821115611dc357600080fd5b50611dd085828601611ba5565b9150509250929050565b600060208284031215611dec57600080fd5b813567ffffffffffffffff811115611e0357600080fd5b61158b84828501611b4f565b600060208284031215611e2157600080fd5b815161111e81611c9f565b600060208284031215611e3e57600080fd5b5051919050565b60005b83811015611e60578181015183820152602001611e48565b50506000910152565b60008151808452611e81816020860160208601611e45565b601f01601f19169290920160200192915050565b60208152600061111e6020830184611e69565b600060208284031215611eba57600080fd5b8151801515811461111e57600080fd5b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611f4157888303603f1901855281518051878552611f1588860182611e69565b91890151858303868b0152919050611f2d8183611e69565b968901969450505090860190600101611ef1565b509098975050505050505050565b60008060408385031215611f6257600080fd5b825167ffffffffffffffff811115611f7957600080fd5b8301601f81018513611f8a57600080fd5b8051611f98611b6e82611b27565b818152866020838501011115611fad57600080fd5b611fbe826020830160208601611e45565b809450505050602083015163ffffffff81168114611fdb57600080fd5b809150509250929050565b634e487b7160e01b600052601160045260246000fd5b808201808211156102e7576102e7611fe6565b818103818111156102e7576102e7611fe6565b6040815260006120356040830185611e69565b905063ffffffff831660208301529392505050565b634e487b7160e01b600052603260045260246000fd5b60008261207d57634e487b7160e01b600052601260045260246000fd5b500690565b60008161209157612091611fe6565b506000190190565b80820281158282048414176102e7576102e7611fe6565b634e487b7160e01b600052600160045260246000fd5b600181815b808511156121015781600019048211156120e7576120e7611fe6565b808516156120f457918102915b93841c93908002906120cb565b509250929050565b600082612118575060016102e7565b81612125575060006102e7565b816001811461213b576002811461214557612161565b60019150506102e7565b60ff84111561215657612156611fe6565b50506001821b6102e7565b5060208310610133831016604e8410600b8410161715612184575081810a6102e7565b61218e83836120c6565b80600019048211156121a2576121a2611fe6565b029392505050565b600061111e8383612109565b81810360008312801583831316838312821617156121d6576121d6611fe6565b509291505056fea2646970667358221220cfdfb6d1279817f31cba3a4d94621dfc051060fc2ac60424bd477a23a28c37d164736f6c63430008110033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100c95760003560e01c806329d56630116100815780636f9512211161005b5780636f951221146101e55780637dc0d1d014610206578063ab14ec591461022d57600080fd5b806329d566301461019857806330349ebe146101ab5780633f15457f146101be57600080fd5b806306963218116100b257806306963218146101355780631ecfc4111461014a57806325916d411461015d57600080fd5b806301ffc9a7146100ce57806304f3bcec146100f6575b600080fd5b6100e16100dc366004611a75565b610254565b60405190151581526020015b60405180910390f35b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100ed565b610148610143366004611cb7565b6102ed565b005b610148610158366004611d40565b6104df565b61018361016b366004611d5d565b60016020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016100ed565b6101486101a6366004611d76565b610656565b60005461011d906001600160a01b031681565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b6101f86101f3366004611dda565b61072a565b6040519081526020016100ed565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102e757507fffffffff0000000000000000000000000000000000000000000000000000000082167f2f43542800000000000000000000000000000000000000000000000000000000145b92915050565b60008060006102fc87876107f8565b91945092509050336001600160a01b0382161461035b576040517fe03f60240000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03821660248201526044015b60405180910390fd5b6040516305ef2c7f60e41b815260048101849052602481018390526001600160a01b0382811660448301528681166064830152600060848301527f00000000000000000000000000000000000000000000000000000000000000001690635ef2c7f09060a401600060405180830381600087803b1580156103db57600080fd5b505af11580156103ef573d6000803e3d6000fd5b505050506001600160a01b038416156104d6576001600160a01b03851661042957604051633c584f1360e21b815260040160405180910390fd5b604080516020810185905290810183905260009060600160408051808303601f190181529082905280516020909101207fd5fa2b00000000000000000000000000000000000000000000000000000000008252600482018190526001600160a01b03878116602484015290925087169063d5fa2b0090604401600060405180830381600087803b1580156104bc57600080fd5b505af11580156104d0573d6000803e3d6000fd5b50505050505b50505050505050565b6040516302571be360e01b8152600060048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015610547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056b9190611e0f565b90506000816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d19190611e0f565b9050336001600160a01b038216146105e857600080fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0385169081179091556040519081527f9176b7f47e4504df5e5516c99d90d82ac7cbd49cc77e7f22ba2ac2f2e3a3eba89060200160405180910390a1505050565b600080600061066585856107f8565b6040517f06ab592300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b03828116604483015293965091945092507f0000000000000000000000000000000000000000000000000000000000000000909116906306ab5923906064016020604051808303816000875af11580156106fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107229190611e2c565b505050505050565b600080546040517f4f89059e0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690634f89059e90610774908590600401611e95565b602060405180830381865afa158015610791573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b59190611ea8565b6107ed57816040517f396e24b80000000000000000000000000000000000000000000000000000000081526004016103529190611e95565b6102e7826000610a35565b60008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bdf95fef876040518263ffffffff1660e01b815260040161084c9190611eca565b600060405180830381865afa158015610869573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108919190810190611f4f565b909250905060006108a28882610e58565b60ff1690506108b388600183610e7c565b945060006108e66108c5836001611ffc565b6001848c516108d4919061200f565b6108de919061200f565b8b9190610ea0565b90506108f18161072a565b965060008787604051602001610911929190918252602082015260400190565b60408051808303601f190181529181528151602092830120600081815260019093529082205490925063ffffffff16850360030b121561097d576040517f2dd6a7af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260408120805463ffffffff191663ffffffff87161790556109a88b87610f22565b9097509050806109e4576040517f6260f6f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b866001600160a01b0316827f87db02a0e483e2818060eddcbb3488ce44e35aff49a70d92c2aa6c8046cf01e28d88604051610a20929190612022565b60405180910390a35050505050509250925092565b600080610a428484610e58565b60ff16905080600003610a595750600090506102e7565b6000610a7985610a698487611ffc565b610a74906001611ffc565b610a35565b90506000610a93610a8b866001611ffc565b879085610e7c565b604080516020810185905290810182905290915060600160408051601f198184030181529082905280516020909101206302571be360e01b82526004820181905294506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906302571be390602401602060405180830381865afa158015610b2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4e9190611e0f565b90506001600160a01b0381161580610b9757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316145b15610e255782610d6a576040516302571be360e01b8152600060048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d9190611e0f565b6040517f8cb8ecec000000000000000000000000000000000000000000000000000000008152600481018590523060248201529091506001600160a01b03821690638cb8ecec90604401600060405180830381600087803b158015610c9157600080fd5b505af1158015610ca5573d6000803e3d6000fd5b50506040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018990526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000169250631896f70a9150604401600060405180830381600087803b158015610d4c57600080fd5b505af1158015610d60573d6000803e3d6000fd5b5050505050610e4e565b6040516305ef2c7f60e41b815260048101849052602481018390523060448201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166064830152600060848301527f00000000000000000000000000000000000000000000000000000000000000001690635ef2c7f09060a401600060405180830381600087803b158015610e0857600080fd5b505af1158015610e1c573d6000803e3d6000fd5b50505050610e4e565b6001600160a01b0381163014610e4e57604051633c584f1360e21b815260040160405180910390fd5b5050505092915050565b6000828281518110610e6c57610e6c61204a565b016020015160f81c905092915050565b8251600090610e8b8385611ffc565b1115610e9657600080fd5b5091016020012090565b8251606090610eaf8385611ffc565b1115610eba57600080fd5b60008267ffffffffffffffff811115610ed557610ed5611ab7565b6040519080825280601f01601f191660200182016040528015610eff576020820181803683370190505b50905060208082019086860101610f17828287611030565b509095945050505050565b600080610f42604051806040016040528060608152602001600081525090565b610f5a85516005610f539190611ffc565b8290611086565b5060408051808201909152600581527f045f656e730000000000000000000000000000000000000000000000000000006020820152610f9a9082906110fd565b50610fa581866110fd565b506000610fb28582611125565b90505b8051516020820151101561101f578151610fd890610fd283611186565b906111a7565b60000361101157600080610ff5878460a001518560c00151611300565b92509050811561100e5794506001935061102992505050565b50505b61101a81611373565b610fb5565b5060008092509250505b9250929050565b602081106110685781518352611047602084611ffc565b9250611054602083611ffc565b915061106160208261200f565b9050611030565b905182516020929092036101000a6000190180199091169116179052565b6040805180820190915260608152600060208201526110a6602083612060565b156110ce576110b6602083612060565b6110c190602061200f565b6110cb9083611ffc565b91505b6020808401839052604051808552600081529081840101818110156110f257600080fd5b604052509192915050565b60408051808201909152606081526000602082015261111e8383845161145b565b9392505050565b6111736040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c081018290526102e781611373565b602081015181516060916102e79161119e9082611531565b84519190610ea0565b60006111b38383611593565b156111c0575060006102e7565b60008060008060006111d38860006115b1565b905060006111e28860006115b1565b90505b8082111561120e578593506111fa898761160e565b95508161120681612082565b9250506111e5565b8181111561123757849250611223888661160e565b94508061122f81612082565b91505061120e565b600082118015611250575061124e89878a88611632565b155b1561128557859350611262898761160e565b9550849250611271888661160e565b945061127e60018361200f565b9150611237565b8560000361129d5760001996505050505050506102e7565b846000036112b457600196505050505050506102e7565b6112f36112c2856001611ffc565b6112cc8b87610e58565b60ff168a6112db876001611ffc565b6112e58d89610e58565b8e949392919060ff16611667565b9998505050505050505050565b6000805b828410156113645760006113188686610e58565b60ff169050611328600186611ffc565b94506000806113388888856117e5565b9250905081156113505793506001925061136b915050565b61135a8388611ffc565b9650505050611304565b5060009050805b935093915050565b60c0810151602082018190528151511161138a5750565b600061139e82600001518360200151611531565b82602001516113ad9190611ffc565b82519091506113bc9082611839565b61ffff1660408301526113d0600282611ffc565b82519091506113df9082611839565b61ffff1660608301526113f3600282611ffc565b82519091506114029082611861565b63ffffffff166080830152611418600482611ffc565b825190915060009061142a9083611839565b61ffff16905061143b600283611ffc565b60a08401819052915061144e8183611ffc565b60c0909301929092525050565b604080518082019091526060815260006020820152825182111561147e57600080fd5b835151600061148d8483611ffc565b905085602001518111156114af576114af866114aa836002612099565b61188b565b8551805183820160200191600091808511156114c9578482525b505050602086015b6020861061150957805182526114e8602083611ffc565b91506114f5602082611ffc565b905061150260208761200f565b95506114d1565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b6000815b83518110611545576115456120b0565b60006115518583610e58565b60ff169050611561816001611ffc565b61156b9083611ffc565b91508060000361157b5750611581565b50611535565b61158b838261200f565b949350505050565b60008151835114801561111e575061111e83600084600087516118a8565b6000805b835183106115c5576115c56120b0565b60006115d18585610e58565b60ff1690506115e1816001611ffc565b6115eb9085611ffc565b9350806000036115fb575061111e565b611606600183611ffc565b9150506115b5565b600061161a8383610e58565b60ff16611628836001611ffc565b61111e9190611ffc565b600061164b8383848651611646919061200f565b610e7c565b61165d8686878951611646919061200f565b1495945050505050565b85516000906116768688611ffc565b11156116aa576116868587611ffc565b8751604051638a3c1cfb60e01b815260048101929092526024820152604401610352565b83516116b68385611ffc565b11156116ea576116c68284611ffc565b8451604051638a3c1cfb60e01b815260048101929092526024820152604401610352565b84808310156116f65750815b60208789018101908587010160005b838110156117ca578251825180821461179a5760006020611726858961200f565b106117345750600019611770565b600187611742866020611ffc565b61174c919061200f565b611757906008612099565b6117629060026121aa565b61176c919061200f565b1990505b60006117808383168584166121b6565b905080156117975797506117db9650505050505050565b50505b6117a5602086611ffc565b94506117b2602085611ffc565b935050506020816117c39190611ffc565b9050611705565b506117d585896121b6565b93505050505b9695505050505050565b6000806117f28585611861565b63ffffffff1663613d30781461180d5750600090508061136b565b61182d61181b856004611ffc565b6118258587611ffc565b8791906118cb565b91509150935093915050565b8151600090611849836002611ffc565b111561185457600080fd5b50016002015161ffff1690565b8151600090611871836004611ffc565b111561187c57600080fd5b50016004015163ffffffff1690565b81516118978383611086565b506118a283826110fd565b50505050565b60006118b5848484610e7c565b6118c0878785610e7c565b149695505050505050565b60008060286118da858561200f565b10156118eb5750600090508061136b565b6000806118f9878787611907565b909890975095505050505050565b60008080611915858561200f565b905080604014158015611929575080602814155b8061193e575061193a600282612060565b6001145b156119a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c696420737472696e67206c656e67746800000000000000000000006044820152606401610352565b6001915085518411156119b757600080fd5b611a08565b6000603a8210602f831116156119d45750602f190190565b604782106040831116156119ea57506036190190565b60678210606083111615611a0057506056190190565b5060ff919050565b60208601855b85811015611a6a57611a258183015160001a6119bc565b611a376001830184015160001a6119bc565b60ff811460ff83141715611a5057600095505050611a6a565b60049190911b1760089590951b9490941793600201611a0e565b505050935093915050565b600060208284031215611a8757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461111e57600080fd5b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611af057611af0611ab7565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611b1f57611b1f611ab7565b604052919050565b600067ffffffffffffffff821115611b4157611b41611ab7565b50601f01601f191660200190565b600082601f830112611b6057600080fd5b8135611b73611b6e82611b27565b611af6565b818152846020838601011115611b8857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112611bb657600080fd5b8135602067ffffffffffffffff80831115611bd357611bd3611ab7565b8260051b611be2838201611af6565b9384528581018301938381019088861115611bfc57600080fd5b84880192505b85831015611c9357823584811115611c1a5760008081fd5b88016040818b03601f1901811315611c325760008081fd5b611c3a611acd565b8783013587811115611c4c5760008081fd5b611c5a8d8a83870101611b4f565b825250908201359086821115611c705760008081fd5b611c7e8c8984860101611b4f565b81890152845250509184019190840190611c02565b98975050505050505050565b6001600160a01b0381168114611cb457600080fd5b50565b60008060008060808587031215611ccd57600080fd5b843567ffffffffffffffff80821115611ce557600080fd5b611cf188838901611b4f565b95506020870135915080821115611d0757600080fd5b50611d1487828801611ba5565b9350506040850135611d2581611c9f565b91506060850135611d3581611c9f565b939692955090935050565b600060208284031215611d5257600080fd5b813561111e81611c9f565b600060208284031215611d6f57600080fd5b5035919050565b60008060408385031215611d8957600080fd5b823567ffffffffffffffff80821115611da157600080fd5b611dad86838701611b4f565b93506020850135915080821115611dc357600080fd5b50611dd085828601611ba5565b9150509250929050565b600060208284031215611dec57600080fd5b813567ffffffffffffffff811115611e0357600080fd5b61158b84828501611b4f565b600060208284031215611e2157600080fd5b815161111e81611c9f565b600060208284031215611e3e57600080fd5b5051919050565b60005b83811015611e60578181015183820152602001611e48565b50506000910152565b60008151808452611e81816020860160208601611e45565b601f01601f19169290920160200192915050565b60208152600061111e6020830184611e69565b600060208284031215611eba57600080fd5b8151801515811461111e57600080fd5b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611f4157888303603f1901855281518051878552611f1588860182611e69565b91890151858303868b0152919050611f2d8183611e69565b968901969450505090860190600101611ef1565b509098975050505050505050565b60008060408385031215611f6257600080fd5b825167ffffffffffffffff811115611f7957600080fd5b8301601f81018513611f8a57600080fd5b8051611f98611b6e82611b27565b818152866020838501011115611fad57600080fd5b611fbe826020830160208601611e45565b809450505050602083015163ffffffff81168114611fdb57600080fd5b809150509250929050565b634e487b7160e01b600052601160045260246000fd5b808201808211156102e7576102e7611fe6565b818103818111156102e7576102e7611fe6565b6040815260006120356040830185611e69565b905063ffffffff831660208301529392505050565b634e487b7160e01b600052603260045260246000fd5b60008261207d57634e487b7160e01b600052601260045260246000fd5b500690565b60008161209157612091611fe6565b506000190190565b80820281158282048414176102e7576102e7611fe6565b634e487b7160e01b600052600160045260246000fd5b600181815b808511156121015781600019048211156120e7576120e7611fe6565b808516156120f457918102915b93841c93908002906120cb565b509250929050565b600082612118575060016102e7565b81612125575060006102e7565b816001811461213b576002811461214557612161565b60019150506102e7565b60ff84111561215657612156611fe6565b50506001821b6102e7565b5060208310610133831016604e8410600b8410161715612184575081810a6102e7565b61218e83836120c6565b80600019048211156121a2576121a2611fe6565b029392505050565b600061111e8383612109565b81810360008312801583831316838312821617156121d6576121d6611fe6565b509291505056fea2646970667358221220cfdfb6d1279817f31cba3a4d94621dfc051060fc2ac60424bd477a23a28c37d164736f6c63430008110033",
  "devdoc": {
    "details": "An ENS registrar that allows the owner of a DNS name to claim the      corresponding name in ENS.",
    "kind": "dev",
    "methods": {
      "proveAndClaim(bytes,(bytes,bytes)[])": {
        "details": "Submits proofs to the DNSSEC oracle, then claims a name using those proofs.",
        "params": {
          "input": "A chain of signed DNS RRSETs ending with a text record.",
          "name": "The name to claim, in DNS wire format."
        }
      }
    },
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 4216,
        "contract": "contracts/dnsregistrar/DNSRegistrar.sol:DNSRegistrar",
        "label": "suffixes",
        "offset": 0,
        "slot": "0",
        "type": "t_contract(PublicSuffixList)5705"
      },
      {
        "astId": 4224,
        "contract": "contracts/dnsregistrar/DNSRegistrar.sol:DNSRegistrar",
        "label": "inceptions",
        "offset": 0,
        "slot": "1",
        "type": "t_mapping(t_bytes32,t_uint32)"
      }
    ],
    "types": {
      "t_bytes32": {
        "encoding": "inplace",
        "label": "bytes32",
        "numberOfBytes": "32"
      },
      "t_contract(PublicSuffixList)5705": {
        "encoding": "inplace",
        "label": "contract PublicSuffixList",
        "numberOfBytes": "20"
      },
      "t_mapping(t_bytes32,t_uint32)": {
        "encoding": "mapping",
        "key": "t_bytes32",
        "label": "mapping(bytes32 => uint32)",
        "numberOfBytes": "32",
        "value": "t_uint32"
      },
      "t_uint32": {
        "encoding": "inplace",
        "label": "uint32",
        "numberOfBytes": "4"
      }
    }
  }
}