{
  "language": "Solidity",
  "sources": {
    "contracts/dnsregistrar/DNSClaimChecker.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"../dnssec-oracle/DNSSEC.sol\";\nimport \"../dnssec-oracle/BytesUtils.sol\";\nimport \"../dnssec-oracle/RRUtils.sol\";\nimport \"@ensdomains/buffer/contracts/Buffer.sol\";\n\nlibrary DNSClaimChecker {\n\n    using BytesUtils 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(DNSSEC oracle, bytes memory name, bytes memory proof)\n        internal\n        view\n        returns (address, bool)\n    {\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        bytes20 hash;\n        uint32 expiration;\n        // Check the provided TXT record has been validated by the oracle\n        (, expiration, hash) = oracle.rrdata(TYPE_TXT, buf.buf);\n        if (hash == bytes20(0) && proof.length == 0) return (address(0x0), false);\n\n        require(hash == bytes20(keccak256(proof)));\n\n        for (RRUtils.RRIterator memory iter = proof.iterateRRs(0); !iter.done(); iter.next()) {\n            require(RRUtils.serialNumberGte(expiration + iter.ttl, uint32(block.timestamp)), \"DNS record is stale; refresh or delete it before proceeding.\");\n\n            bool found;\n            address addr;\n            (addr, found) = parseRR(proof, iter.rdataOffset);\n            if (found) {\n                return (addr, true);\n            }\n        }\n\n        return (address(0x0), false);\n    }\n\n    function parseRR(bytes memory rdata, uint idx) internal pure returns (address, bool) {\n        while (idx < rdata.length) {\n            uint len = rdata.readUint8(idx); 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(bytes memory str, uint idx, uint len) 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        if (len < 44) return (address(0x0), false);\n        return hexToAddress(str, idx + 4);\n    }\n\n    function hexToAddress(bytes memory str, uint idx) internal pure returns (address, bool) {\n        if (str.length - idx < 40) return (address(0x0), false);\n        uint ret = 0;\n        for (uint i = idx; i < idx + 40; i++) {\n            ret <<= 4;\n            uint x = str.readUint8(i);\n            if (x >= 48 && x < 58) {\n                ret |= x - 48;\n            } else if (x >= 65 && x < 71) {\n                ret |= x - 55;\n            } else if (x >= 97 && x < 103) {\n                ret |= x - 87;\n            } else {\n                return (address(0x0), false);\n            }\n        }\n        return (address(uint160(ret)), true);\n    }\n}\n"
    },
    "contracts/dnssec-oracle/DNSSEC.sol": {
      "content": "pragma solidity ^0.8.4;\npragma experimental ABIEncoderV2;\n\nabstract contract DNSSEC {\n\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    event NSEC3DigestUpdated(uint8 id, address addr);\n    event RRSetUpdated(bytes name, bytes rrset);\n\n    function submitRRSets(RRSetWithSignature[] memory input, bytes calldata proof) public virtual returns (bytes memory);\n    function submitRRSet(RRSetWithSignature calldata input, bytes calldata proof) public virtual returns (bytes memory);\n    function deleteRRSet(uint16 deleteType, bytes calldata deleteName, RRSetWithSignature calldata nsec, bytes calldata proof) public virtual;\n    function deleteRRSetNSEC3(uint16 deleteType, bytes memory deleteName, RRSetWithSignature memory closestEncloser, RRSetWithSignature memory nextClosest, bytes memory dnskey) public virtual;\n    function rrdata(uint16 dnstype, bytes calldata name) external virtual view returns (uint32, uint32, bytes20);\n}\n"
    },
    "contracts/dnssec-oracle/BytesUtils.sol": {
      "content": "pragma solidity ^0.8.4;\n\nlibrary BytesUtils {\n    /*\n    * @dev Returns the keccak-256 hash of a byte range.\n    * @param self The byte string to hash.\n    * @param offset The position to start hashing at.\n    * @param len The number of bytes to hash.\n    * @return The hash of the byte range.\n    */\n    function keccak(bytes memory self, uint offset, uint len) 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    /*\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(bytes memory self, bytes memory other) internal pure returns (int) {\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(bytes memory self, uint offset, uint len, bytes memory other, uint otheroffset, uint otherlen) internal pure returns (int) {\n        uint shortest = len;\n        if (otherlen < len)\n        shortest = otherlen;\n\n        uint selfptr;\n        uint otherptr;\n\n        assembly {\n            selfptr := add(self, add(offset, 32))\n            otherptr := add(other, add(otheroffset, 32))\n        }\n        for (uint idx = 0; idx < shortest; idx += 32) {\n            uint a;\n            uint b;\n            assembly {\n                a := mload(selfptr)\n                b := mload(otherptr)\n            }\n            if (a != b) {\n                // Mask out irrelevant bytes and check again\n                uint mask;\n                if (shortest > 32) {\n                    mask = type(uint256).max;\n                } else {\n                    mask = ~(2 ** (8 * (32 - shortest + idx)) - 1);\n                }\n                int diff = int(a & mask) - int(b & mask);\n                if (diff != 0)\n                return diff;\n            }\n            selfptr += 32;\n            otherptr += 32;\n        }\n\n        return int(len) - int(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(bytes memory self, uint offset, bytes memory other, uint otherOffset, uint len) 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(bytes memory self, uint offset, bytes memory other, uint otherOffset) internal pure returns (bool) {\n        return keccak(self, offset, self.length - offset) == 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(bytes memory self, uint offset, bytes memory other) internal pure returns (bool) {\n        return self.length >= offset + other.length && 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(bytes memory self, bytes memory other) internal pure returns(bool) {\n        return self.length == other.length && 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(bytes memory self, uint idx) 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(bytes memory self, uint idx) 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(bytes memory self, uint idx) 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(bytes memory self, uint idx) 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(bytes memory self, uint idx) internal pure returns (bytes20 ret) {\n        require(idx + 20 <= self.length);\n        assembly {\n            ret := and(mload(add(add(self, 32), idx)), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000)\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(bytes memory self, uint idx, uint len) 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(uint dest, uint src, uint 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            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\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(bytes memory self, uint offset, uint len) internal pure returns(bytes memory) {\n        require(offset + len <= self.length);\n\n        bytes memory ret = new bytes(len);\n        uint dest;\n        uint 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 = 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(bytes memory self, uint off, uint len) internal pure returns(bytes32) {\n        require(len <= 52);\n\n        uint ret = 0;\n        uint8 decoded;\n        for(uint i = 0; i < len; i++) {\n            bytes1 char = self[off + i];\n            require(char >= 0x30 && char <= 0x7A);\n            decoded = uint8(base32HexTable[uint(uint8(char)) - 0x30]);\n            require(decoded <= 0x20);\n            if(i == len - 1) {\n                break;\n            }\n            ret = (ret << 5) | decoded;\n        }\n\n        uint 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}"
    },
    "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(bytes memory self, uint offset) internal pure returns(uint) {\n        uint idx = offset;\n        while (true) {\n            assert(idx < self.length);\n            uint 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(bytes memory self, uint offset) internal pure returns(bytes memory ret) {\n        uint 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(bytes memory self, uint offset) internal pure returns(uint) {\n        uint count = 0;\n        while (true) {\n            assert(offset < self.length);\n            uint 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    uint constant RRSIG_TYPE = 0;\n    uint constant RRSIG_ALGORITHM = 2;\n    uint constant RRSIG_LABELS = 3;\n    uint constant RRSIG_TTL = 4;\n    uint constant RRSIG_EXPIRATION = 8;\n    uint constant RRSIG_INCEPTION = 12;\n    uint constant RRSIG_KEY_TAG = 16;\n    uint 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(bytes memory data) 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(RRSIG_SIGNER_NAME + self.signerName.length, data.length - RRSIG_SIGNER_NAME - self.signerName.length);\n    }\n\n    function rrs(SignedSet memory rrset) 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        uint offset;\n        uint16 dnstype;\n        uint16 class;\n        uint32 ttl;\n        uint rdataOffset;\n        uint 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(bytes memory self, uint offset) 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        uint 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        uint 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 iter.data.substring(iter.offset, nameLength(iter.data, iter.offset));\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(RRIterator memory iter) internal pure returns(bytes memory) {\n        return iter.data.substring(iter.rdataOffset, iter.nextOffset - iter.rdataOffset);\n    }\n\n    uint constant DNSKEY_FLAGS = 0;\n    uint constant DNSKEY_PROTOCOL = 2;\n    uint constant DNSKEY_ALGORITHM = 3;\n    uint 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(bytes memory data, uint offset, uint length) 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(offset + DNSKEY_PUBKEY, length - DNSKEY_PUBKEY);\n    } \n\n    uint constant DS_KEY_TAG = 0;\n    uint constant DS_ALGORITHM = 2;\n    uint constant DS_DIGEST_TYPE = 3;\n    uint 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(bytes memory data, uint offset, uint length) 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    struct NSEC3 {\n        uint8 hashAlgorithm;\n        uint8 flags;\n        uint16 iterations;\n        bytes salt;\n        bytes32 nextHashedOwnerName;\n        bytes typeBitmap;\n    }\n\n    uint constant NSEC3_HASH_ALGORITHM = 0;\n    uint constant NSEC3_FLAGS = 1;\n    uint constant NSEC3_ITERATIONS = 2;\n    uint constant NSEC3_SALT_LENGTH = 4;\n    uint constant NSEC3_SALT = 5;\n\n    function readNSEC3(bytes memory data, uint offset, uint length) internal pure returns(NSEC3 memory self) {\n        uint end = offset + length;\n        self.hashAlgorithm = data.readUint8(offset + NSEC3_HASH_ALGORITHM);\n        self.flags = data.readUint8(offset + NSEC3_FLAGS);\n        self.iterations = data.readUint16(offset + NSEC3_ITERATIONS);\n        uint8 saltLength = data.readUint8(offset + NSEC3_SALT_LENGTH);\n        offset = offset + NSEC3_SALT;\n        self.salt = data.substring(offset, saltLength);\n        offset += saltLength;\n        uint8 nextLength = data.readUint8(offset);\n        require(nextLength <= 32);\n        offset += 1;\n        self.nextHashedOwnerName = data.readBytesN(offset, nextLength);\n        offset += nextLength;\n        self.typeBitmap = data.substring(offset, end - offset);\n    }\n\n    function checkTypeBitmap(NSEC3 memory self, uint16 rrtype) internal pure returns(bool) {\n        return checkTypeBitmap(self.typeBitmap, 0, rrtype);\n    }\n\n    /**\n    * @dev Checks if a given RR type exists in a type bitmap.\n    * @param bitmap The byte string to read the type bitmap from.\n    * @param offset The offset to start reading at.\n    * @param rrtype The RR type to check for.\n    * @return True if the type is found in the bitmap, false otherwise.\n    */\n    function checkTypeBitmap(bytes memory bitmap, uint offset, uint16 rrtype) internal pure returns (bool) {\n        uint8 typeWindow = uint8(rrtype >> 8);\n        uint8 windowByte = uint8((rrtype & 0xff) / 8);\n        uint8 windowBitmask = uint8(uint8(1) << (uint8(7) - uint8(rrtype & 0x7)));\n        for (uint off = offset; off < bitmap.length;) {\n            uint8 window = bitmap.readUint8(off);\n            uint8 len = bitmap.readUint8(off + 1);\n            if (typeWindow < window) {\n                // We've gone past our window; it's not here.\n                return false;\n            } else if (typeWindow == window) {\n                // Check this type bitmap\n                if (len <= windowByte) {\n                    // Our type is past the end of the bitmap\n                    return false;\n                }\n                return (bitmap.readUint8(off + windowByte + 2) & windowBitmask) != 0;\n            } else {\n                // Skip this type bitmap\n                off += len + 2;\n            }\n        }\n\n        return false;\n    }\n\n    function compareNames(bytes memory self, bytes memory other) internal pure returns (int) {\n        if (self.equals(other)) {\n            return 0;\n        }\n\n        uint off;\n        uint otheroff;\n        uint prevoff;\n        uint otherprevoff;\n        uint counts = labelCount(self, 0);\n        uint 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 self.compare(prevoff + 1, self.readUint8(prevoff), other, otherprevoff + 1, other.readUint8(otherprevoff));\n    }\n\n    /**\n     * @dev Compares two serial numbers using RFC1982 serial number math.\n     */\n    function serialNumberGte(uint32 i1, uint32 i2) internal pure returns(bool) {\n        return int32(i1) - int32(i2) >= 0;\n    }\n\n    function progress(bytes memory body, uint off) internal pure returns(uint) {\n        return off + 1 + body.readUint8(off);\n    }\n}"
    },
    "@ensdomains/buffer/contracts/Buffer.sol": {
      "content": "pragma 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 writing 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            mstore(0x40, add(32, add(ptr, capacity)))\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    function max(uint a, uint b) private pure returns(uint) {\n        if (a > b) {\n            return a;\n        }\n        return b;\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 Writes 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 off The start offset to write 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 write(buffer memory buf, uint off, bytes memory data, uint len) internal pure returns(buffer memory) {\n        require(len <= data.length);\n\n        if (off + len > buf.capacity) {\n            resize(buf, max(buf.capacity, len + off) * 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(add(len, off), buflen) {\n                mstore(bufptr, add(len, off))\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    * @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        return write(buf, buf.buf.length, data, len);\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 write(buf, buf.buf.length, data, data.length);\n    }\n\n    /**\n    * @dev Writes 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 off The offset to write the byte at.\n    * @param data The data to append.\n    * @return The original buffer, for chaining.\n    */\n    function writeUint8(buffer memory buf, uint off, uint8 data) internal pure returns(buffer memory) {\n        if (off >= buf.capacity) {\n            resize(buf, buf.capacity * 2);\n        }\n\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            // 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 eq(off, buflen) {\n                mstore(bufptr, add(buflen, 1))\n            }\n        }\n        return buf;\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        return writeUint8(buf, buf.buf.length, data);\n    }\n\n    /**\n    * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would\n    *      exceed the capacity of the buffer.\n    * @param buf The buffer to append to.\n    * @param off The offset to write at.\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 write(buffer memory buf, uint off, bytes32 data, uint len) private pure returns(buffer memory) {\n        if (len + off > buf.capacity) {\n            resize(buf, (len + off) * 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) + off + len\n                let dest := add(add(bufptr, off), len)\n                mstore(dest, or(and(mload(dest), not(mask)), data))\n                // Update buffer length if we extended it\n                if gt(add(off, len), mload(bufptr)) {\n                    mstore(bufptr, add(off, len))\n                }\n            }\n        }\n        return buf;\n    }\n\n    /**\n    * @dev Writes a bytes20 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 off The offset to write at.\n    * @param data The data to append.\n    * @return The original buffer, for chaining.\n    */\n    function writeBytes20(buffer memory buf, uint off, bytes20 data) internal pure returns (buffer memory) {\n        return write(buf, off, bytes32(data), 20);\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 write(buf, buf.buf.length, 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 write(buf, buf.buf.length, data, 32);\n    }\n\n    /**\n    * @dev Writes an integer 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 off The offset to write at.\n    * @param data The data to append.\n    * @param len The number of bytes to write (right-aligned).\n    * @return The original buffer, for chaining.\n    */\n    function writeInt(buffer memory buf, uint off, uint data, uint len) private pure returns(buffer memory) {\n        if (len + off > buf.capacity) {\n            resize(buf, (len + off) * 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 + off + sizeof(buffer length) + len\n            let dest := add(add(bufptr, off), len)\n            mstore(dest, or(and(mload(dest), not(mask)), data))\n            // Update buffer length if we extended it\n            if gt(add(off, len), mload(bufptr)) {\n                mstore(bufptr, add(off, len))\n            }\n        }\n        return buf;\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     * @return The original buffer.\n     */\n    function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {\n        return writeInt(buf, buf.buf.length, data, len);\n    }\n}\n"
    },
    "contracts/dnsregistrar/DNSRegistrar.sol": {
      "content": "pragma solidity ^0.8.4;\npragma experimental ABIEncoderV2;\n\nimport \"../dnssec-oracle/BytesUtils.sol\";\nimport \"../dnssec-oracle/DNSSEC.sol\";\nimport \"../registry/ENSRegistry.sol\";\nimport \"../root/Root.sol\";\nimport \"./DNSClaimChecker.sol\";\nimport \"./PublicSuffixList.sol\";\nimport \"../resolvers/profiles/AddrResolver.sol\";\n\ninterface IDNSRegistrar {\n    function claim(bytes memory name, bytes memory proof) external;\n    function proveAndClaim(bytes memory name, DNSSEC.RRSetWithSignature[] memory input, bytes memory proof) external;\n    function proveAndClaimWithResolver(bytes memory name, DNSSEC.RRSetWithSignature[] memory input, bytes memory proof, address resolver, address addr) external;\n}\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 {\n    using BytesUtils for bytes;\n\n    DNSSEC public oracle;\n    ENS public ens;\n    PublicSuffixList public suffixes;\n\n    bytes4 constant private INTERFACE_META_ID = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n\n    event Claim(bytes32 indexed node, address indexed owner, bytes dnsname);\n    event NewOracle(address oracle);\n    event NewPublicSuffixList(address suffixes);\n\n    constructor(DNSSEC _dnssec, PublicSuffixList _suffixes, ENS _ens) {\n        oracle = _dnssec;\n        emit NewOracle(address(oracle));\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 setOracle(DNSSEC _dnssec) public onlyOwner {\n        oracle = _dnssec;\n        emit NewOracle(address(oracle));\n    }\n\n    function setPublicSuffixList(PublicSuffixList _suffixes) public onlyOwner {\n        suffixes = _suffixes;\n        emit NewPublicSuffixList(address(suffixes));\n    }\n\n    /**\n     * @dev Claims a name by proving ownership of its DNS equivalent.\n     * @param name The name to claim, in DNS wire format.\n     * @param proof A DNS RRSet proving ownership of the name. Must be verified\n     *        in the DNSSEC oracle before calling. This RRSET must contain a TXT\n     *        record for '_ens.' + name, with the value 'a=0x...'. Ownership of\n     *        the name will be transferred to the address specified in the TXT\n     *        record.\n     */\n    function claim(bytes memory name, bytes memory proof) public override {\n        (bytes32 rootNode, bytes32 labelHash, address addr) = _claim(name, proof);\n        ens.setSubnodeOwner(rootNode, labelHash, addr);\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 The data to be passed to the Oracle's `submitProofs` function. The last\n     *        proof must be the TXT record required by the registrar.\n     * @param proof The proof record for the first element in input.\n     */\n    function proveAndClaim(bytes memory name, DNSSEC.RRSetWithSignature[] memory input, bytes memory proof) public override {\n        proof = oracle.submitRRSets(input, proof);\n        claim(name, proof);\n    }\n\n    function proveAndClaimWithResolver(bytes memory name, DNSSEC.RRSetWithSignature[] memory input, bytes memory proof, address resolver, address addr) public override {\n        proof = oracle.submitRRSets(input, proof);\n        (bytes32 rootNode, bytes32 labelHash, address owner) = _claim(name, proof);\n        require(msg.sender == owner, \"Only owner can call proveAndClaimWithResolver\");\n        if(addr != address(0)) {\n            require(resolver != address(0), \"Cannot set addr if resolver is not set\");\n            // Set ourselves as the owner so we can set a record on the resolver\n            ens.setSubnodeRecord(rootNode, labelHash, address(this), resolver, 0);\n            bytes32 node = keccak256(abi.encodePacked(rootNode, labelHash));\n            // Set the resolver record\n            AddrResolver(resolver).setAddr(node, addr);\n            // Transfer the record to the owner\n            ens.setOwner(node, owner);\n        } else {\n            ens.setSubnodeRecord(rootNode, labelHash, owner, resolver, 0);\n        }\n    }\n\n    function supportsInterface(bytes4 interfaceID) external pure returns (bool) {\n        return interfaceID == INTERFACE_META_ID ||\n               interfaceID == type(IDNSRegistrar).interfaceId;\n    }\n\n    function _claim(bytes memory name, bytes memory proof) internal returns(bytes32 rootNode, bytes32 labelHash, address addr) {\n        // Get the first label\n        uint labelLen = name.readUint8(0);\n        labelHash = name.keccak(1, labelLen);\n\n        // Parent name must be in the public suffix list.\n        bytes memory parentName = name.substring(labelLen + 1, name.length - labelLen - 1);\n        require(suffixes.isPublicSuffix(parentName), \"Parent name must be a public suffix\");\n\n        // Make sure the parent name is enabled\n        rootNode = enableNode(parentName, 0);\n\n        (addr,) = DNSClaimChecker.getOwnerAddress(oracle, name, proof);\n\n        emit Claim(keccak256(abi.encodePacked(rootNode, labelHash)), addr, name);\n    }\n\n    function enableNode(bytes memory domain, uint offset) internal returns(bytes32 node) {\n        uint 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        require(owner == address(0) || owner == address(this), \"Cannot enable a name owned by someone else\");\n        if(owner != address(this)) {\n            if(parentNode == bytes32(0)) {\n                Root root = Root(ens.owner(bytes32(0)));\n                root.setSubnodeOwner(label, address(this));\n            } else {\n                ens.setSubnodeOwner(parentNode, label, address(this));\n            }\n        }\n        return node;\n    }\n}\n"
    },
    "contracts/registry/ENSRegistry.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"./ENS.sol\";\n\n/**\n * The ENS registry contract.\n */\ncontract ENSRegistry is ENS {\n\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 registrar.\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(bytes32 node, address owner, address resolver, uint64 ttl) 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(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) 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(bytes32 node, address owner) 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(bytes32 node, bytes32 label, address owner) 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(bytes32 node, address resolver) 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(bytes32 node, uint64 ttl) 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(address operator, bool approved) 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(bytes32 node) public virtual override view 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(bytes32 node) public virtual override view 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 virtual override view 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(bytes32 node) public virtual override view 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(address owner, address operator) external virtual override view 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(bytes32 node, address resolver, uint64 ttl) internal {\n        if(resolver != records[node].resolver) {\n            records[node].resolver = resolver;\n            emit NewResolver(node, resolver);\n        }\n\n        if(ttl != records[node].ttl) {\n            records[node].ttl = ttl;\n            emit NewTTL(node, ttl);\n        }\n    }\n}\n"
    },
    "contracts/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(bytes32 label, address owner)\n        external\n        onlyController\n    {\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(bytes4 interfaceID)\n        external\n        pure\n        returns (bool)\n    {\n        return interfaceID == INTERFACE_META_ID;\n    }\n}\n"
    },
    "contracts/dnsregistrar/PublicSuffixList.sol": {
      "content": "pragma solidity ^0.8.4;\n\ninterface PublicSuffixList {\n    function isPublicSuffix(bytes calldata name) external view returns(bool);\n}\n"
    },
    "contracts/resolvers/profiles/AddrResolver.sol": {
      "content": "pragma solidity >=0.8.4;\nimport \"../ResolverBase.sol\";\n\nabstract contract AddrResolver is ResolverBase {\n    bytes4 constant private ADDR_INTERFACE_ID = 0x3b3b57de;\n    bytes4 constant private ADDRESS_INTERFACE_ID = 0xf1cb7e06;\n    uint constant private COIN_TYPE_ETH = 60;\n\n    event AddrChanged(bytes32 indexed node, address a);\n    event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress);\n\n    mapping(bytes32=>mapping(uint=>bytes)) _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(bytes32 node, address a) external 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(bytes32 node) public view 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(bytes32 node, uint coinType, bytes memory a) public authorised(node) {\n        emit AddressChanged(node, coinType, a);\n        if(coinType == COIN_TYPE_ETH) {\n            emit AddrChanged(node, bytesToAddress(a));\n        }\n        _addresses[node][coinType] = a;\n    }\n\n    function addr(bytes32 node, uint coinType) public view returns(bytes memory) {\n        return _addresses[node][coinType];\n    }\n\n    function supportsInterface(bytes4 interfaceID) virtual override public pure returns(bool) {\n        return interfaceID == ADDR_INTERFACE_ID || interfaceID == ADDRESS_INTERFACE_ID || super.supportsInterface(interfaceID);\n    }\n\n    function bytesToAddress(bytes memory b) internal pure returns(address payable a) {\n        require(b.length == 20);\n        assembly {\n            a := div(mload(add(b, 32)), exp(256, 12))\n        }\n    }\n\n    function addressToBytes(address a) internal pure returns(bytes memory b) {\n        b = new bytes(20);\n        assembly {\n            mstore(add(b, 32), mul(a, exp(256, 12)))\n        }\n    }\n}\n"
    },
    "contracts/registry/ENS.sol": {
      "content": "pragma solidity >=0.8.4;\n\ninterface ENS {\n\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(address indexed owner, address indexed operator, bool approved);\n\n    function setRecord(bytes32 node, address owner, address resolver, uint64 ttl) external virtual;\n    function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external virtual;\n    function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external virtual returns(bytes32);\n    function setResolver(bytes32 node, address resolver) external virtual;\n    function setOwner(bytes32 node, address owner) external virtual;\n    function setTTL(bytes32 node, uint64 ttl) external virtual;\n    function setApprovalForAll(address operator, bool approved) external virtual;\n    function owner(bytes32 node) external virtual view returns (address);\n    function resolver(bytes32 node) external virtual view returns (address);\n    function ttl(bytes32 node) external virtual view returns (uint64);\n    function recordExists(bytes32 node) external virtual view returns (bool);\n    function isApprovedForAll(address owner, address operator) external virtual view returns (bool);\n}\n"
    },
    "@openzeppelin/contracts/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\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        address msgSender = _msgSender();\n        _owner = msgSender;\n        emit OwnershipTransferred(address(0), msgSender);\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 called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\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        emit OwnershipTransferred(_owner, address(0));\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\n        _owner = newOwner;\n    }\n}\n"
    },
    "contracts/root/Controllable.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract Controllable is Ownable {\n    mapping(address => bool) public controllers;\n\n    event ControllerChanged(address indexed controller, bool enabled);\n\n    modifier onlyController {\n        require(\n            controllers[msg.sender],\n            \"Controllable: Caller is not a controller\"\n        );\n        _;\n    }\n\n    function setController(address controller, bool enabled) public onlyOwner {\n        controllers[controller] = enabled;\n        emit ControllerChanged(controller, enabled);\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\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        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n        return msg.data;\n    }\n}\n"
    },
    "contracts/resolvers/ResolverBase.sol": {
      "content": "pragma solidity >=0.8.4;\nabstract contract ResolverBase {\n    bytes4 private constant INTERFACE_META_ID = 0x01ffc9a7;\n\n    function supportsInterface(bytes4 interfaceID) virtual public pure returns(bool) {\n        return interfaceID == INTERFACE_META_ID;\n    }\n\n    function isAuthorised(bytes32 node) internal virtual view returns(bool);\n\n    modifier authorised(bytes32 node) {\n        require(isAuthorised(node));\n        _;\n    }\n}\n"
    },
    "contracts/resolvers/PublicResolver.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"../registry/ENS.sol\";\nimport \"./profiles/ABIResolver.sol\";\nimport \"./profiles/AddrResolver.sol\";\nimport \"./profiles/ContentHashResolver.sol\";\nimport \"./profiles/DNSResolver.sol\";\nimport \"./profiles/InterfaceResolver.sol\";\nimport \"./profiles/NameResolver.sol\";\nimport \"./profiles/PubkeyResolver.sol\";\nimport \"./profiles/TextResolver.sol\";\n\ninterface INameWrapper {\n    function ownerOf(uint256 id) external view returns (address);\n}\n\n/**\n * A simple resolver anyone can use; only allows the owner of a node to set its\n * address.\n */\ncontract PublicResolver is ABIResolver, AddrResolver, ContentHashResolver, DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver {\n    ENS ens;\n    INameWrapper nameWrapper;\n\n    /**\n     * A mapping of operators. An address that is authorised for an address\n     * may make any changes to the name that the owner could, but may not update\n     * the set of authorisations.\n     * (owner, operator) => approved\n     */\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n    // Logged when an operator is added or removed.\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    constructor(ENS _ens, INameWrapper wrapperAddress){\n        ens = _ens;\n        nameWrapper = wrapperAddress;\n    }\n\n    /**\n     * @dev See {IERC1155-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) external{\n        require(\n            msg.sender != operator,\n            \"ERC1155: setting approval status for self\"\n        );\n\n        _operatorApprovals[msg.sender][operator] = approved;\n        emit ApprovalForAll(msg.sender, operator, approved);\n    }\n\n    function isAuthorised(bytes32 node) internal override view returns(bool) {\n        address owner = ens.owner(node);\n        if(owner == address(nameWrapper) ){\n            owner = nameWrapper.ownerOf(uint256(node));\n        }\n        return owner == msg.sender || isApprovedForAll(owner, msg.sender);\n    }\n\n    /**\n     * @dev See {IERC1155-isApprovedForAll}.\n     */\n    function isApprovedForAll(address account, address operator) public view returns (bool){\n        return _operatorApprovals[account][operator];\n    }\n\n    function multicall(bytes[] calldata data) external returns(bytes[] memory results) {\n        results = new bytes[](data.length);\n        for(uint i = 0; i < data.length; i++) {\n            (bool success, bytes memory result) = address(this).delegatecall(data[i]);\n            require(success);\n            results[i] = result;\n        }\n        return results;\n    }\n\n    function supportsInterface(bytes4 interfaceID) virtual override(ABIResolver, AddrResolver, ContentHashResolver, DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver) public pure returns(bool) {\n        return super.supportsInterface(interfaceID);\n    }\n}\n"
    },
    "contracts/resolvers/profiles/ABIResolver.sol": {
      "content": "pragma solidity >=0.8.4;\nimport \"../ResolverBase.sol\";\n\nabstract contract ABIResolver is ResolverBase {\n    bytes4 constant private ABI_INTERFACE_ID = 0x2203ab56;\n\n    event ABIChanged(bytes32 indexed node, uint256 indexed contentType);\n\n    mapping(bytes32=>mapping(uint256=>bytes)) abis;\n\n    /**\n     * Sets the ABI associated with an ENS node.\n     * Nodes may have one ABI of each content type. To remove an ABI, set it to\n     * the empty string.\n     * @param node The node to update.\n     * @param contentType The content type of the ABI\n     * @param data The ABI data.\n     */\n    function setABI(bytes32 node, uint256 contentType, bytes calldata data) external authorised(node) {\n        // Content types must be powers of 2\n        require(((contentType - 1) & contentType) == 0);\n\n        abis[node][contentType] = data;\n        emit ABIChanged(node, contentType);\n    }\n\n    /**\n     * Returns the ABI associated with an ENS node.\n     * Defined in EIP205.\n     * @param node The ENS node to query\n     * @param contentTypes A bitwise OR of the ABI formats accepted by the caller.\n     * @return contentType The content type of the return value\n     * @return data The ABI data\n     */\n    function ABI(bytes32 node, uint256 contentTypes) external view returns (uint256, bytes memory) {\n        mapping(uint256=>bytes) storage abiset = abis[node];\n\n        for (uint256 contentType = 1; contentType <= contentTypes; contentType <<= 1) {\n            if ((contentType & contentTypes) != 0 && abiset[contentType].length > 0) {\n                return (contentType, abiset[contentType]);\n            }\n        }\n\n        return (0, bytes(\"\"));\n    }\n\n    function supportsInterface(bytes4 interfaceID) virtual override public pure returns(bool) {\n        return interfaceID == ABI_INTERFACE_ID || super.supportsInterface(interfaceID);\n    }\n}\n"
    },
    "contracts/resolvers/profiles/ContentHashResolver.sol": {
      "content": "pragma solidity >=0.8.4;\nimport \"../ResolverBase.sol\";\n\nabstract contract ContentHashResolver is ResolverBase {\n    bytes4 constant private CONTENT_HASH_INTERFACE_ID = 0xbc1c58d1;\n\n    event ContenthashChanged(bytes32 indexed node, bytes hash);\n\n    mapping(bytes32=>bytes) hashes;\n\n    /**\n     * Sets the contenthash 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 hash The contenthash to set\n     */\n    function setContenthash(bytes32 node, bytes calldata hash) external authorised(node) {\n        hashes[node] = hash;\n        emit ContenthashChanged(node, hash);\n    }\n\n    /**\n     * Returns the contenthash associated with an ENS node.\n     * @param node The ENS node to query.\n     * @return The associated contenthash.\n     */\n    function contenthash(bytes32 node) external view returns (bytes memory) {\n        return hashes[node];\n    }\n\n    function supportsInterface(bytes4 interfaceID) virtual override public pure returns(bool) {\n        return interfaceID == CONTENT_HASH_INTERFACE_ID || super.supportsInterface(interfaceID);\n    }\n}\n"
    },
    "contracts/resolvers/profiles/DNSResolver.sol": {
      "content": "pragma solidity >=0.8.4;\nimport \"../ResolverBase.sol\";\nimport \"../../dnssec-oracle/RRUtils.sol\";\n\nabstract contract DNSResolver is ResolverBase {\n    using RRUtils for *;\n    using BytesUtils for bytes;\n\n    bytes4 constant private DNS_RECORD_INTERFACE_ID = 0xa8fa5682;\n    bytes4 constant private DNS_ZONE_INTERFACE_ID = 0x5c47637c;\n\n    // DNSRecordChanged is emitted whenever a given node/name/resource's RRSET is updated.\n    event DNSRecordChanged(bytes32 indexed node, bytes name, uint16 resource, bytes record);\n    // DNSRecordDeleted is emitted whenever a given node/name/resource's RRSET is deleted.\n    event DNSRecordDeleted(bytes32 indexed node, bytes name, uint16 resource);\n    // DNSZoneCleared is emitted whenever a given node's zone information is cleared.\n    event DNSZoneCleared(bytes32 indexed node);\n\n    // DNSZonehashChanged is emitted whenever a given node's zone hash is updated.\n    event DNSZonehashChanged(bytes32 indexed node, bytes lastzonehash, bytes zonehash);\n\n    // Zone hashes for the domains.\n    // A zone hash is an EIP-1577 content hash in binary format that should point to a\n    // resource containing a single zonefile.\n    // node => contenthash\n    mapping(bytes32=>bytes) private zonehashes;\n\n    // Version the mapping for each zone.  This allows users who have lost\n    // track of their entries to effectively delete an entire zone by bumping\n    // the version number.\n    // node => version\n    mapping(bytes32=>uint256) private versions;\n\n    // The records themselves.  Stored as binary RRSETs\n    // node => version => name => resource => data\n    mapping(bytes32=>mapping(uint256=>mapping(bytes32=>mapping(uint16=>bytes)))) private records;\n\n    // Count of number of entries for a given name.  Required for DNS resolvers\n    // when resolving wildcards.\n    // node => version => name => number of records\n    mapping(bytes32=>mapping(uint256=>mapping(bytes32=>uint16))) private nameEntriesCount;\n\n    /**\n     * Set one or more DNS records.  Records are supplied in wire-format.\n     * Records with the same node/name/resource must be supplied one after the\n     * other to ensure the data is updated correctly. For example, if the data\n     * was supplied:\n     *     a.example.com IN A 1.2.3.4\n     *     a.example.com IN A 5.6.7.8\n     *     www.example.com IN CNAME a.example.com.\n     * then this would store the two A records for a.example.com correctly as a\n     * single RRSET, however if the data was supplied:\n     *     a.example.com IN A 1.2.3.4\n     *     www.example.com IN CNAME a.example.com.\n     *     a.example.com IN A 5.6.7.8\n     * then this would store the first A record, the CNAME, then the second A\n     * record which would overwrite the first.\n     *\n     * @param node the namehash of the node for which to set the records\n     * @param data the DNS wire format records to set\n     */\n    function setDNSRecords(bytes32 node, bytes calldata data) external authorised(node) {\n        uint16 resource = 0;\n        uint256 offset = 0;\n        bytes memory name;\n        bytes memory value;\n        bytes32 nameHash;\n        // Iterate over the data to add the resource records\n        for (RRUtils.RRIterator memory iter = data.iterateRRs(0); !iter.done(); iter.next()) {\n            if (resource == 0) {\n                resource = iter.dnstype;\n                name = iter.name();\n                nameHash = keccak256(abi.encodePacked(name));\n                value = bytes(iter.rdata());\n            } else {\n                bytes memory newName = iter.name();\n                if (resource != iter.dnstype || !name.equals(newName)) {\n                    setDNSRRSet(node, name, resource, data, offset, iter.offset - offset, value.length == 0);\n                    resource = iter.dnstype;\n                    offset = iter.offset;\n                    name = newName;\n                    nameHash = keccak256(name);\n                    value = bytes(iter.rdata());\n                }\n            }\n        }\n        if (name.length > 0) {\n            setDNSRRSet(node, name, resource, data, offset, data.length - offset, value.length == 0);\n        }\n    }\n\n    /**\n     * Obtain a DNS record.\n     * @param node the namehash of the node for which to fetch the record\n     * @param name the keccak-256 hash of the fully-qualified name for which to fetch the record\n     * @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types\n     * @return the DNS record in wire format if present, otherwise empty\n     */\n    function dnsRecord(bytes32 node, bytes32 name, uint16 resource) public view returns (bytes memory) {\n        return records[node][versions[node]][name][resource];\n    }\n\n    /**\n     * Check if a given node has records.\n     * @param node the namehash of the node for which to check the records\n     * @param name the namehash of the node for which to check the records\n     */\n    function hasDNSRecords(bytes32 node, bytes32 name) public view returns (bool) {\n        return (nameEntriesCount[node][versions[node]][name] != 0);\n    }\n\n    /**\n     * Clear all information for a DNS zone.\n     * @param node the namehash of the node for which to clear the zone\n     */\n    function clearDNSZone(bytes32 node) public authorised(node) {\n        versions[node]++;\n        emit DNSZoneCleared(node);\n    }\n\n    /**\n     * setZonehash sets the hash for the zone.\n     * May only be called by the owner of that node in the ENS registry.\n     * @param node The node to update.\n     * @param hash The zonehash to set\n     */\n    function setZonehash(bytes32 node, bytes calldata hash) external authorised(node) {\n        bytes memory oldhash = zonehashes[node];\n        zonehashes[node] = hash;\n        emit DNSZonehashChanged(node, oldhash, hash);\n    }\n\n    /**\n     * zonehash obtains the hash for the zone.\n     * @param node The ENS node to query.\n     * @return The associated contenthash.\n     */\n    function zonehash(bytes32 node) external view returns (bytes memory) {\n        return zonehashes[node];\n    }\n\n    function supportsInterface(bytes4 interfaceID) virtual override public pure returns(bool) {\n        return interfaceID == DNS_RECORD_INTERFACE_ID ||\n               interfaceID == DNS_ZONE_INTERFACE_ID ||\n               super.supportsInterface(interfaceID);\n    }\n\n    function setDNSRRSet(\n        bytes32 node,\n        bytes memory name,\n        uint16 resource,\n        bytes memory data,\n        uint256 offset,\n        uint256 size,\n        bool deleteRecord) private\n    {\n        uint256 version = versions[node];\n        bytes32 nameHash = keccak256(name);\n        bytes memory rrData = data.substring(offset, size);\n        if (deleteRecord) {\n            if (records[node][version][nameHash][resource].length != 0) {\n                nameEntriesCount[node][version][nameHash]--;\n            }\n            delete(records[node][version][nameHash][resource]);\n            emit DNSRecordDeleted(node, name, resource);\n        } else {\n            if (records[node][version][nameHash][resource].length == 0) {\n                nameEntriesCount[node][version][nameHash]++;\n            }\n            records[node][version][nameHash][resource] = rrData;\n            emit DNSRecordChanged(node, name, resource, rrData);\n        }\n    }\n}\n"
    },
    "contracts/resolvers/profiles/InterfaceResolver.sol": {
      "content": "pragma solidity >=0.8.4;\nimport \"../ResolverBase.sol\";\nimport \"./AddrResolver.sol\";\n\nabstract contract InterfaceResolver is ResolverBase, AddrResolver {\n    bytes4 constant private INTERFACE_INTERFACE_ID = bytes4(keccak256(\"interfaceImplementer(bytes32,bytes4)\"));\n    bytes4 private constant INTERFACE_META_ID = 0x01ffc9a7;\n\n    event InterfaceChanged(bytes32 indexed node, bytes4 indexed interfaceID, address implementer);\n\n    mapping(bytes32=>mapping(bytes4=>address)) interfaces;\n\n    /**\n     * Sets an interface associated with a name.\n     * Setting the address to 0 restores the default behaviour of querying the contract at `addr()` for interface support.\n     * @param node The node to update.\n     * @param interfaceID The EIP 165 interface ID.\n     * @param implementer The address of a contract that implements this interface for this node.\n     */\n    function setInterface(bytes32 node, bytes4 interfaceID, address implementer) external authorised(node) {\n        interfaces[node][interfaceID] = implementer;\n        emit InterfaceChanged(node, interfaceID, implementer);\n    }\n\n    /**\n     * Returns the address of a contract that implements the specified interface for this name.\n     * If an implementer has not been set for this interfaceID and name, the resolver will query\n     * the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that\n     * contract implements EIP165 and returns `true` for the specified interfaceID, its address\n     * will be returned.\n     * @param node The ENS node to query.\n     * @param interfaceID The EIP 165 interface ID to check for.\n     * @return The address that implements this interface, or 0 if the interface is unsupported.\n     */\n    function interfaceImplementer(bytes32 node, bytes4 interfaceID) external view returns (address) {\n        address implementer = interfaces[node][interfaceID];\n        if(implementer != address(0)) {\n            return implementer;\n        }\n\n        address a = addr(node);\n        if(a == address(0)) {\n            return address(0);\n        }\n\n        (bool success, bytes memory returnData) = a.staticcall(abi.encodeWithSignature(\"supportsInterface(bytes4)\", INTERFACE_META_ID));\n        if(!success || returnData.length < 32 || returnData[31] == 0) {\n            // EIP 165 not supported by target\n            return address(0);\n        }\n\n        (success, returnData) = a.staticcall(abi.encodeWithSignature(\"supportsInterface(bytes4)\", interfaceID));\n        if(!success || returnData.length < 32 || returnData[31] == 0) {\n            // Specified interface not supported by target\n            return address(0);\n        }\n\n        return a;\n    }\n\n    function supportsInterface(bytes4 interfaceID) virtual override(AddrResolver, ResolverBase) public pure returns(bool) {\n        return interfaceID == INTERFACE_INTERFACE_ID || super.supportsInterface(interfaceID);\n    }\n}\n"
    },
    "contracts/resolvers/profiles/NameResolver.sol": {
      "content": "pragma solidity >=0.8.4;\nimport \"../ResolverBase.sol\";\n\nabstract contract NameResolver is ResolverBase {\n    bytes4 constant private NAME_INTERFACE_ID = 0x691f3431;\n\n    event NameChanged(bytes32 indexed node, string name);\n\n    mapping(bytes32=>string) names;\n\n    /**\n     * Sets the name associated with an ENS node, for reverse records.\n     * May only be called by the owner of that node in the ENS registry.\n     * @param node The node to update.\n     * @param name The name to set.\n     */\n    function setName(bytes32 node, string calldata name) external authorised(node) {\n        names[node] = name;\n        emit NameChanged(node, name);\n    }\n\n    /**\n     * Returns the name associated with an ENS node, for reverse records.\n     * Defined in EIP181.\n     * @param node The ENS node to query.\n     * @return The associated name.\n     */\n    function name(bytes32 node) external view returns (string memory) {\n        return names[node];\n    }\n\n    function supportsInterface(bytes4 interfaceID) virtual override public pure returns(bool) {\n        return interfaceID == NAME_INTERFACE_ID || super.supportsInterface(interfaceID);\n    }\n}\n"
    },
    "contracts/resolvers/profiles/PubkeyResolver.sol": {
      "content": "pragma solidity >=0.8.4;\nimport \"../ResolverBase.sol\";\n\nabstract contract PubkeyResolver is ResolverBase {\n    bytes4 constant private PUBKEY_INTERFACE_ID = 0xc8690233;\n\n    event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);\n\n    struct PublicKey {\n        bytes32 x;\n        bytes32 y;\n    }\n\n    mapping(bytes32=>PublicKey) pubkeys;\n\n    /**\n     * Sets the SECP256k1 public key associated with an ENS node.\n     * @param node The ENS node to query\n     * @param x the X coordinate of the curve point for the public key.\n     * @param y the Y coordinate of the curve point for the public key.\n     */\n    function setPubkey(bytes32 node, bytes32 x, bytes32 y) external authorised(node) {\n        pubkeys[node] = PublicKey(x, y);\n        emit PubkeyChanged(node, x, y);\n    }\n\n    /**\n     * Returns the SECP256k1 public key associated with an ENS node.\n     * Defined in EIP 619.\n     * @param node The ENS node to query\n     * @return x The X coordinate of the curve point for the public key.\n     * @return y The Y coordinate of the curve point for the public key.\n     */\n    function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y) {\n        return (pubkeys[node].x, pubkeys[node].y);\n    }\n\n    function supportsInterface(bytes4 interfaceID) virtual override public pure returns(bool) {\n        return interfaceID == PUBKEY_INTERFACE_ID || super.supportsInterface(interfaceID);\n    }\n}\n"
    },
    "contracts/resolvers/profiles/TextResolver.sol": {
      "content": "pragma solidity >=0.8.4;\nimport \"../ResolverBase.sol\";\n\nabstract contract TextResolver is ResolverBase {\n    bytes4 constant private TEXT_INTERFACE_ID = 0x59d1d43c;\n\n    event TextChanged(bytes32 indexed node, string indexed indexedKey, string key);\n\n    mapping(bytes32=>mapping(string=>string)) texts;\n\n    /**\n     * Sets the text data associated with an ENS node and key.\n     * May only be called by the owner of that node in the ENS registry.\n     * @param node The node to update.\n     * @param key The key to set.\n     * @param value The text data value to set.\n     */\n    function setText(bytes32 node, string calldata key, string calldata value) external authorised(node) {\n        texts[node][key] = value;\n        emit TextChanged(node, key, key);\n    }\n\n    /**\n     * Returns the text data associated with an ENS node and key.\n     * @param node The ENS node to query.\n     * @param key The text data key to query.\n     * @return The associated text data.\n     */\n    function text(bytes32 node, string calldata key) external view returns (string memory) {\n        return texts[node][key];\n    }\n\n    function supportsInterface(bytes4 interfaceID) virtual override public pure returns(bool) {\n        return interfaceID == TEXT_INTERFACE_ID || super.supportsInterface(interfaceID);\n    }\n}\n"
    },
    "contracts/resolvers/OwnedResolver.sol": {
      "content": "pragma solidity >=0.8.4;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./profiles/ABIResolver.sol\";\nimport \"./profiles/AddrResolver.sol\";\nimport \"./profiles/ContentHashResolver.sol\";\nimport \"./profiles/DNSResolver.sol\";\nimport \"./profiles/InterfaceResolver.sol\";\nimport \"./profiles/NameResolver.sol\";\nimport \"./profiles/PubkeyResolver.sol\";\nimport \"./profiles/TextResolver.sol\";\n\n/**\n * A simple resolver anyone can use; only allows the owner of a node to set its\n * address.\n */\ncontract OwnedResolver is Ownable, ABIResolver, AddrResolver, ContentHashResolver, DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver {\n    function isAuthorised(bytes32 node) internal override view returns(bool) {\n        return msg.sender == owner();\n    }\n\n    function supportsInterface(bytes4 interfaceID) virtual override(ABIResolver, AddrResolver, ContentHashResolver, DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver) public pure returns(bool) {\n        return super.supportsInterface(interfaceID);\n    }\n}\n"
    },
    "test/dnssec-oracle/TestRRUtils.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"../../contracts/dnssec-oracle/RRUtils.sol\";\nimport \"../../contracts/dnssec-oracle/BytesUtils.sol\";\n\ncontract TestRRUtils {\n  using BytesUtils for *;\n  using RRUtils for *;\n\n  uint16 constant DNSTYPE_A = 1;\n  uint16 constant DNSTYPE_CNAME = 5;\n  uint16 constant DNSTYPE_MX = 15;\n  uint16 constant DNSTYPE_TEXT = 16;\n  uint16 constant DNSTYPE_RRSIG = 46;\n  uint16 constant DNSTYPE_NSEC = 47;\n  uint16 constant DNSTYPE_TYPE1234 = 1234;\n\n  function testNameLength() public pure {\n    require(hex'00'.nameLength(0) == 1, \"nameLength('.') == 1\");\n    require(hex'0361626300'.nameLength(4) == 1, \"nameLength('.') == 1\");\n    require(hex'0361626300'.nameLength(0) == 5, \"nameLength('abc.') == 5\");\n  }\n\n  function testLabelCount() public pure {\n    require(hex'00'.labelCount(0) == 0, \"labelCount('.') == 0\");\n    require(hex'016100'.labelCount(0) == 1, \"labelCount('a.') == 1\");\n    require(hex'016201610000'.labelCount(0) == 2, \"labelCount('b.a.') == 2\");\n    require(hex'066574686c61620378797a00'.labelCount(6 +1) == 1, \"nameLength('(bthlab).xyz.') == 6\");\n  }\n\n  function testIterateRRs() public pure {\n    // a. IN A 3600 127.0.0.1\n    // b.a. IN A 3600 192.168.1.1\n    bytes memory rrs = hex'0161000001000100000e1000047400000101620161000001000100000e100004c0a80101';\n    string[2] memory names = [hex'016100', hex'0162016100'];\n    string[2] memory rdatas = [hex'74000001', hex'c0a80101'];\n    uint i = 0;\n    for(RRUtils.RRIterator memory iter = rrs.iterateRRs(0); !iter.done(); iter.next()) {\n      require(uint(iter.dnstype) == 1, \"Type matches\");\n      require(uint(iter.class) == 1, \"Class matches\");\n      require(uint(iter.ttl) == 3600, \"TTL matches\");\n      require(keccak256(iter.name()) == keccak256(bytes(names[i])), \"Name matches\");\n      require(keccak256(iter.rdata()) == keccak256(bytes(rdatas[i])), \"Rdata matches\");\n      i++;\n    }\n    require(i == 2, \"Expected 2 records\");\n  }\n\n  function testCheckTypeBitmapTextType() public pure {\n    bytes memory tb = hex'0003000080';\n    require(tb.checkTypeBitmap(0, DNSTYPE_TEXT) == true, \"A record should exist in type bitmap\");\n  }\n\n  function testCheckTypeBitmap() public pure {\n    // From https://tools.ietf.org/html/rfc4034#section-4.3\n    //    alfa.example.com. 86400 IN NSEC host.example.com. (\n    //                               A MX RRSIG NSEC TYPE1234\n    bytes memory tb = hex'FF0006400100000003041b000000000000000000000000000000000000000000000000000020';\n\n    // Exists in bitmap\n    require(tb.checkTypeBitmap(1, DNSTYPE_A) == true, \"A record should exist in type bitmap\");\n    // Does not exist, but in a window that is included\n    require(tb.checkTypeBitmap(1, DNSTYPE_CNAME) == false, \"CNAME record should not exist in type bitmap\");\n    // Does not exist, past the end of a window that is included\n    require(tb.checkTypeBitmap(1, 64) == false, \"Type 64 should not exist in type bitmap\");\n    // Does not exist, in a window that does not exist\n    require(tb.checkTypeBitmap(1, 769) == false, \"Type 769 should not exist in type bitmap\");\n    // Exists in a subsequent window\n    require(tb.checkTypeBitmap(1, DNSTYPE_TYPE1234) == true, \"Type 1234 should exist in type bitmap\");\n    // Does not exist, past the end of the bitmap windows\n    require(tb.checkTypeBitmap(1, 1281) == false, \"Type 1281 should not exist in type bitmap\");\n  }\n\n  // Canonical ordering https://tools.ietf.org/html/rfc4034#section-6.1\n  function testCompareNames() public pure {\n    bytes memory bthLabXyz = hex'066274686c61620378797a00';\n    bytes memory ethLabXyz = hex'066574686c61620378797a00';\n    bytes memory xyz = hex'0378797a00';\n    bytes memory a_b_c  = hex'01610162016300';\n    bytes memory b_b_c  = hex'01620162016300';\n    bytes memory c      = hex'016300';\n    bytes memory d      = hex'016400';\n    bytes memory a_d_c  = hex'01610164016300';\n    bytes memory b_a_c  = hex'01620161016300';\n    bytes memory ab_c_d = hex'0261620163016400';\n    bytes memory a_c_d  = hex'01610163016400';\n\n    require(hex'0301616100'.compareNames(hex'0302616200') <  0,  \"label lengths are correctly checked\");\n    require(a_b_c.compareNames(c)      >  0,  \"one name has a difference of >1 label to with the same root name\");\n    require(a_b_c.compareNames(d)      <  0, \"one name has a difference of >1 label to with different root name\");\n    require(a_b_c.compareNames(a_d_c)  <  0, \"two names start the same but have differences in later labels\");\n    require(a_b_c.compareNames(b_a_c)  >  0, \"the first label sorts later, but the first label sorts earlier\");\n    require(ab_c_d.compareNames(a_c_d) >  0, \"two names where the first label on one is a prefix of the first label on the other\");\n    require(a_b_c.compareNames(b_b_c)  <  0, \"two names where the first label on one is a prefix of the first label on the other\");\n    require(xyz.compareNames(ethLabXyz) < 0, \"xyz comes before ethLab.xyz\");\n    require(bthLabXyz.compareNames(ethLabXyz) < 0, \"bthLab.xyz comes before ethLab.xyz\");\n    require(bthLabXyz.compareNames(bthLabXyz) == 0, \"bthLab.xyz and bthLab.xyz are the same\");\n    require(ethLabXyz.compareNames(bthLabXyz) >  0, \"ethLab.xyz comes after bethLab.xyz\");\n    require(bthLabXyz.compareNames(xyz)       >  0, \"bthLab.xyz comes after xyz\");\n  }\n\n  function testSerialNumberGt() public pure {\n    require(RRUtils.serialNumberGte(1, 0), \"1 >= 0\");\n    require(!RRUtils.serialNumberGte(0, 1), \"!(0 <= 1)\");\n    require(RRUtils.serialNumberGte(0, 0xFFFFFFFF), \"0 >= 0xFFFFFFFF\");\n    require(!RRUtils.serialNumberGte(0xFFFFFFFF, 0), \"!(0 <= 0xFFFFFFFF)\");\n    require(RRUtils.serialNumberGte(0x11111111, 0xAAAAAAAA), \"0x11111111 >= 0xAAAAAAAA\");\n    require(RRUtils.serialNumberGte(1, 1), \"1 >= 1\");\n  }\n}"
    },
    "test/dnssec-oracle/TestBytesUtils.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"../../contracts/dnssec-oracle/RRUtils.sol\";\nimport \"../../contracts/dnssec-oracle/BytesUtils.sol\";\n\ncontract TestBytesUtils {\n  using BytesUtils for *;\n\n  function testKeccak() public pure {\n    require(\"\".keccak(0, 0) == bytes32(0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470), \"Incorrect hash of empty string\");\n    require(\"foo\".keccak(0, 3) == bytes32(0x41b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d), \"Incorrect hash of 'foo'\");\n    require(\"foo\".keccak(0, 0) == bytes32(0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470), \"Incorrect hash of empty string\");\n  }\n\n  function testEquals() public pure {\n    require(\"hello\".equals(\"hello\") == true, \"String equality\");\n    require(\"hello\".equals(\"goodbye\") == false, \"String inequality\");\n    require(\"hello\".equals(1, \"ello\") == true, \"Substring to string equality\");\n    require(\"hello\".equals(1, \"jello\", 1, 4) == true, \"Substring to substring equality\");\n    require(\"zhello\".equals(1, \"abchello\", 3) == true,   \"Compare different value with multiple length\");\n  }\n\n  function testComparePartial() public pure {\n    require(\"xax\".compare(1, 1, \"xxbxx\", 2, 1)   < 0 == true,  \"Compare same length\");\n    require(\"xax\".compare(1, 1, \"xxabxx\", 2, 2)  < 0 == true,  \"Compare different length\");\n    require(\"xax\".compare(1, 1, \"xxaxx\", 2, 1)  == 0 == true,  \"Compare same with different offset\");\n  }\n\n  function testCompare() public pure {\n    require(\"a\".compare(\"a\")  == 0 == true,  \"Compare equal\");\n    require(\"a\".compare(\"b\")   < 0 == true,   \"Compare different value with same length\");\n    require(\"b\".compare(\"a\")   > 0 == true,   \"Compare different value with same length\");\n    require(\"aa\".compare(\"ab\") < 0 == true,   \"Compare different value with multiple length\");\n    require(\"a\".compare(\"aa\")  < 0 == true,   \"Compare different value with different length\");\n    require(\"aa\".compare(\"a\")  > 0 == true,   \"Compare different value with different length\");\n    bytes memory longChar = \"1234567890123456789012345678901234\";\n    require(longChar.compare(longChar) == 0 == true,   \"Compares more than 32 bytes char\");\n    bytes memory otherLongChar = \"2234567890123456789012345678901234\";\n    require(longChar.compare(otherLongChar) < 0 == true,   \"Compare long char with difference at start\");\n  }\n\n  function testSubstring() public pure {\n    require(keccak256(bytes(\"hello\".substring(0, 0))) == keccak256(bytes(\"\")), \"Copy 0 bytes\");\n    require(keccak256(bytes(\"hello\".substring(0, 4))) == keccak256(bytes(\"hell\")), \"Copy substring\");\n    require(keccak256(bytes(\"hello\".substring(1, 4))) == keccak256(bytes(\"ello\")), \"Copy substring\");\n    require(keccak256(bytes(\"hello\".substring(0, 5))) == keccak256(bytes(\"hello\")), \"Copy whole string\");\n  }\n\n  function testReadUint8() public pure {\n    require(uint(\"a\".readUint8(0)) == 0x61, \"a == 0x61\");\n    require(uint(\"ba\".readUint8(1)) == 0x61, \"a == 0x61\");\n  }\n\n  function testReadUint16() public pure {\n    require(uint(\"abc\".readUint16(1)) == 0x6263, \"Read uint 16\");\n  }\n\n  function testReadUint32() public pure {\n    require(uint(\"abcde\".readUint32(1)) == 0x62636465, \"Read uint 32\");\n  }\n\n  function testReadBytes20() public pure {\n    require(bytes32(\"abcdefghijklmnopqrstuv\".readBytes20(1)) == bytes32(0x62636465666768696a6b6c6d6e6f707172737475000000000000000000000000), \"readBytes20\");\n  }\n\n  function testReadBytes32() public pure {\n    require(\"0123456789abcdef0123456789abcdef\".readBytes32(0) == bytes32(0x3031323334353637383961626364656630313233343536373839616263646566), \"readBytes32\");\n  }\n\n  function testBase32HexDecodeWord() public pure {\n    require(\"C4\".base32HexDecodeWord(0, 2) == bytes32(bytes1(\"a\")), \"Decode 'a'\");\n    require(\"C5GG\".base32HexDecodeWord(0, 4) == bytes32(bytes2(\"aa\")), \"Decode 'aa'\");\n    require(\"C5GM2\".base32HexDecodeWord(0, 5) == bytes32(bytes3(\"aaa\")), \"Decode 'aaa'\");\n    require(\"C5GM2O8\".base32HexDecodeWord(0, 7) == bytes32(bytes4(\"aaaa\")), \"Decode 'aaaa'\");\n    require(\"C5GM2OB1\".base32HexDecodeWord(0, 8) == bytes32(bytes5(\"aaaaa\")), \"Decode 'aaaaa'\");\n    require(\"c5gm2Ob1\".base32HexDecodeWord(0, 8) == bytes32(bytes5(\"aaaaa\")), \"Decode 'aaaaa' lowercase\");\n    require(\"C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8\".base32HexDecodeWord(0, 42) == bytes32(bytes26(\"abcdefghijklmnopqrstuvwxyz\")), \"Decode alphabet\");\n    require(\"c5h66p35cpjmgqbaddm6qrjfe1on4srkelr7eu3pf8\".base32HexDecodeWord(0, 42) == bytes32(bytes26(\"abcdefghijklmnopqrstuvwxyz\")), \"Decode alphabet lowercase\");\n    require(\"C5GM2OB1C5GM2OB1C5GM2OB1C5GM2OB1C5GM2OB1C5GM2OB1C5GG\".base32HexDecodeWord(0, 52) == bytes32(\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"), \"Decode 32*'a'\");\n    require(\" bst4hlje7r0o8c8p4o8q582lm0ejmiqt\\x07matoken\\x03xyz\\x00\".base32HexDecodeWord(1, 32) == bytes32(hex\"5f3a48d66e3ec18431192611a2a055b01d3b4b5d\"), \"Decode real bytes32hex\");\n  }\n}"
    },
    "contracts/dnssec-oracle/DNSSECImpl.sol": {
      "content": "pragma solidity ^0.8.4;\npragma experimental ABIEncoderV2;\n\nimport \"./Owned.sol\";\nimport \"./BytesUtils.sol\";\nimport \"./RRUtils.sol\";\nimport \"./DNSSEC.sol\";\nimport \"./algorithms/Algorithm.sol\";\nimport \"./digests/Digest.sol\";\nimport \"./nsec3digests/NSEC3Digest.sol\";\nimport \"@ensdomains/buffer/contracts/Buffer.sol\";\n\n/*\n * @dev An oracle contract that verifies and stores DNSSEC-validated DNS records.\n *\n * TODO: Support for NSEC3 records\n */\ncontract DNSSECImpl is DNSSEC, Owned {\n    using Buffer for Buffer.buffer;\n    using BytesUtils for bytes;\n    using RRUtils for *;\n\n    uint16 constant DNSCLASS_IN = 1;\n\n    uint16 constant DNSTYPE_NS = 2;\n    uint16 constant DNSTYPE_SOA = 6;\n    uint16 constant DNSTYPE_DNAME = 39;\n    uint16 constant DNSTYPE_DS = 43;\n    uint16 constant DNSTYPE_RRSIG = 46;\n    uint16 constant DNSTYPE_NSEC = 47;\n    uint16 constant DNSTYPE_DNSKEY = 48;\n    uint16 constant DNSTYPE_NSEC3 = 50;\n\n    uint constant DNSKEY_FLAG_ZONEKEY = 0x100;\n\n    uint8 constant ALGORITHM_RSASHA256 = 8;\n\n    uint8 constant DIGEST_ALGORITHM_SHA256 = 2;\n\n    struct RRSet {\n        uint32 inception;\n        uint32 expiration;\n        bytes20 hash;\n    }\n\n    // (name, type) => RRSet\n    mapping (bytes32 => mapping(uint16 => RRSet)) rrsets;\n\n    mapping (uint8 => Algorithm) public algorithms;\n    mapping (uint8 => Digest) public digests;\n    mapping (uint8 => NSEC3Digest) public nsec3Digests;\n\n    event Test(uint t);\n    event Marker();\n\n    /**\n     * @dev Constructor.\n     * @param _anchors The binary format RR entries for the root DS records.\n     */\n    constructor(bytes memory _anchors) {\n        // Insert the 'trust anchors' - the key hashes that start the chain\n        // of trust for all other records.\n        anchors = _anchors;\n        rrsets[keccak256(hex\"00\")][DNSTYPE_DS] = RRSet({\n            inception: uint32(0),\n            expiration: uint32(3767581600), // May 22 2089 - the latest date we can encode as of writing this\n            hash: bytes20(keccak256(anchors))\n        });\n        emit RRSetUpdated(hex\"00\", anchors);\n    }\n\n    /**\n     * @dev Sets the contract address for a signature verification algorithm.\n     *      Callable only by the owner.\n     * @param id The algorithm ID\n     * @param algo The address of the algorithm contract.\n     */\n    function setAlgorithm(uint8 id, Algorithm algo) public owner_only {\n        algorithms[id] = algo;\n        emit AlgorithmUpdated(id, address(algo));\n    }\n\n    /**\n     * @dev Sets the contract address for a digest verification algorithm.\n     *      Callable only by the owner.\n     * @param id The digest ID\n     * @param digest The address of the digest contract.\n     */\n    function setDigest(uint8 id, Digest digest) public owner_only {\n        digests[id] = digest;\n        emit DigestUpdated(id, address(digest));\n    }\n\n    /**\n     * @dev Sets the contract address for an NSEC3 digest algorithm.\n     *      Callable only by the owner.\n     * @param id The digest ID\n     * @param digest The address of the digest contract.\n     */\n    function setNSEC3Digest(uint8 id, NSEC3Digest digest) public owner_only {\n        nsec3Digests[id] = digest;\n        emit NSEC3DigestUpdated(id, address(digest));\n    }\n\n    /**\n     * @dev Submits multiple RRSets\n     * @param input A list of RRSets and signatures forming a chain of trust from an existing known-good record.\n     * @param _proof The DNSKEY or DS to validate the first signature against.\n     * @return The last RRSET submitted.\n     */\n    function submitRRSets(RRSetWithSignature[] memory input, bytes calldata _proof) public override returns (bytes memory) {\n        bytes memory proof = _proof;\n        for(uint i = 0; i < input.length; i++) {\n            proof = _submitRRSet(input[i], proof);\n        }\n        return proof;\n    }\n\n    /**\n     * @dev Submits a signed set of RRs to the oracle.\n     *\n     * RRSETs are only accepted if they are signed with a key that is already\n     * trusted, or if they are self-signed, and the signing key is identified by\n     * a DS record that is already trusted.\n     *\n     * @param input The signed RR set. This is in the format described in section\n     *        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature\n     *        data, followed by a series of canonicalised RR records that the signature\n     *        applies to.\n     * @param proof The DNSKEY or DS to validate the signature against. Must Already\n     *        have been submitted and proved previously.\n     */\n    function submitRRSet(RRSetWithSignature memory input, bytes memory proof)\n        public override\n        returns (bytes memory)\n    {\n        return _submitRRSet(input, proof);\n    }\n\n    /**\n     * @dev Deletes an RR from the oracle.\n     *\n     * @param deleteType The DNS record type to delete.\n     * @param deleteName which you want to delete\n     * @param nsec The signed NSEC RRset. This is in the format described in section\n     *        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature\n     *        data, followed by a series of canonicalised RR records that the signature\n     *        applies to.\n     */\n    function deleteRRSet(uint16 deleteType, bytes memory deleteName, RRSetWithSignature memory nsec, bytes memory proof)\n        public override\n    {\n        RRUtils.SignedSet memory rrset;\n        rrset = validateSignedSet(nsec, proof);\n        require(rrset.typeCovered == DNSTYPE_NSEC);\n\n        // Don't let someone use an old proof to delete a new name\n        require(RRUtils.serialNumberGte(rrset.inception, rrsets[keccak256(deleteName)][deleteType].inception));\n\n        for (RRUtils.RRIterator memory iter = rrset.rrs(); !iter.done(); iter.next()) {\n            // We're dealing with three names here:\n            //   - deleteName is the name the user wants us to delete\n            //   - nsecName is the owner name of the NSEC record\n            //   - nextName is the next name specified in the NSEC record\n            //\n            // And three cases:\n            //   - deleteName equals nsecName, in which case we can delete the\n            //     record if it's not in the type bitmap.\n            //   - nextName comes after nsecName, in which case we can delete\n            //     the record if deleteName comes between nextName and nsecName.\n            //   - nextName comes before nsecName, in which case nextName is the\n            //     zone apex, and deleteName must come after nsecName.\n            checkNsecName(iter, rrset.name, deleteName, deleteType);\n            delete rrsets[keccak256(deleteName)][deleteType];\n            return;\n        }\n        // We should never reach this point\n        revert();\n    }\n\n    function checkNsecName(RRUtils.RRIterator memory iter, bytes memory nsecName, bytes memory deleteName, uint16 deleteType) private pure {\n        uint rdataOffset = iter.rdataOffset;\n        uint nextNameLength = iter.data.nameLength(rdataOffset);\n        uint rDataLength = iter.nextOffset - iter.rdataOffset;\n\n        // We assume that there is always typed bitmap after the next domain name\n        require(rDataLength > nextNameLength);\n\n        int compareResult = deleteName.compareNames(nsecName);\n        if(compareResult == 0) {\n            // Name to delete is on the same label as the NSEC record\n            require(!iter.data.checkTypeBitmap(rdataOffset + nextNameLength, deleteType));\n        } else {\n            // First check if the NSEC next name comes after the NSEC name.\n            bytes memory nextName = iter.data.substring(rdataOffset,nextNameLength);\n            // deleteName must come after nsecName\n            require(compareResult > 0);\n            if(nsecName.compareNames(nextName) < 0) {\n                // deleteName must also come before nextName\n                require(deleteName.compareNames(nextName) < 0);\n            }\n        }\n    }\n\n    /**\n     * @dev Deletes an RR from the oracle using an NSEC3 proof.\n     *      Deleting a record using NSEC3 requires using up to two NSEC3 records. There are two cases:\n     *       1. The name exists, but the record type doesn't. Eg, example.com has A records but no TXT records.\n     *       2. The name does not exist, but a parent name does.\n     *      In the first case, we submit one NSEC3 proof in `closestEncloser` that matches the target name\n     *      but does not have the bit for `deleteType` set in its type bitmap. In the second case, we submit\n     *      two proofs: closestEncloser and nextClosest, that together prove that the name does not exist.\n     *      NSEC3 records are in the format described in section 5.3.2 of RFC4035: The RRDATA section\n     *      from the RRSIG without the signature data, followed by a series of canonicalised RR records\n     *      that the signature applies to.\n     *\n     * @param deleteType The DNS record type to delete.\n     * @param deleteName The name to delete.\n     * @param closestEncloser An NSEC3 proof matching the closest enclosing name - that is,\n     *        the nearest ancestor of the target name that *does* exist.\n     * @param nextClosest An NSEC3 proof covering the next closest name. This proves that the immediate\n     *        subdomain of the closestEncloser does not exist.\n     * @param dnskey An encoded DNSKEY record that has already been submitted to the oracle and can be used\n     *        to verify the signatures closestEncloserSig and nextClosestSig\n     */\n    function deleteRRSetNSEC3(uint16 deleteType, bytes memory deleteName, RRSetWithSignature memory closestEncloser, RRSetWithSignature memory nextClosest, bytes memory dnskey)\n        public override\n    {\n        uint32 originalInception = rrsets[keccak256(deleteName)][deleteType].inception;\n\n        RRUtils.SignedSet memory ce = validateSignedSet(closestEncloser, dnskey);\n        checkNSEC3Validity(ce, deleteName, originalInception);\n\n        RRUtils.SignedSet memory nc;\n        if(nextClosest.rrset.length > 0) {\n            nc = validateSignedSet(nextClosest, dnskey);\n            checkNSEC3Validity(nc, deleteName, originalInception);\n        }\n\n        RRUtils.NSEC3 memory ceNSEC3 = readNSEC3(ce);\n        // The flags field must be 0 or 1 (RFC5155 section 8.2).\n        require(ceNSEC3.flags & 0xfe == 0);\n        // Check that the closest encloser is from the correct zone (RFC5155 section 8.3)\n        // \"The DNAME type bit must not be set and the NS type bit may only be set if the SOA type bit is set.\"\n        require(!ceNSEC3.checkTypeBitmap(DNSTYPE_DNAME) && (!ceNSEC3.checkTypeBitmap(DNSTYPE_NS) || ceNSEC3.checkTypeBitmap(DNSTYPE_SOA)));\n\n        // Case 1: deleteName does exist, but no records of RRTYPE deleteType do.\n        if(isMatchingNSEC3Record(deleteType, deleteName, ce.name, ceNSEC3)) {\n            delete rrsets[keccak256(deleteName)][deleteType];\n        // Case 2: deleteName does not exist.\n        } else if(isCoveringNSEC3Record(deleteName, ce.name, ceNSEC3, nc.name, readNSEC3(nc))) {\n            delete rrsets[keccak256(deleteName)][deleteType];\n        } else {\n            revert();\n        }\n    }\n\n    function checkNSEC3Validity(RRUtils.SignedSet memory nsec, bytes memory deleteName, uint32 originalInception) private pure {\n        // The records must have been signed after the record we're trying to delete\n        require(RRUtils.serialNumberGte(nsec.inception, originalInception));\n\n        // The record must be an NSEC3\n        require(nsec.typeCovered == DNSTYPE_NSEC3);\n\n        // nsecName is of the form <hash>.zone.xyz. <hash> is the NSEC3 hash of the entire name the NSEC3 record matches, while\n        // zone.xyz can be any ancestor of that name. We'll check that, so someone can't use a record on foo.com\n        // as proof of the nonexistence of bar.org.\n        require(checkNSEC3OwnerName(nsec.name, deleteName));\n    }\n\n    function isMatchingNSEC3Record(uint16 deleteType, bytes memory deleteName, bytes memory closestEncloserName, RRUtils.NSEC3 memory closestEncloser) private view returns(bool) {\n        // Check the record matches the hashed name, but the type bitmap does not include the type\n        if(checkNSEC3Name(closestEncloser, closestEncloserName, deleteName)) {\n            return !closestEncloser.checkTypeBitmap(deleteType);\n        }\n\n        return false;\n    }\n\n    function isCoveringNSEC3Record(bytes memory deleteName, bytes memory ceName, RRUtils.NSEC3 memory ce, bytes memory ncName, RRUtils.NSEC3 memory nc) private view returns(bool) {\n        // The flags field must be 0 or 1 (RFC5155 section 8.2).\n        require(nc.flags & 0xfe == 0);\n\n        bytes32 ceNameHash = decodeOwnerNameHash(ceName);\n        bytes32 ncNameHash = decodeOwnerNameHash(ncName);\n\n        uint lastOffset = 0;\n        // Iterate over suffixes of the name to delete until one matches the closest encloser\n        for(uint offset = deleteName.readUint8(0) + 1; offset < deleteName.length; offset += deleteName.readUint8(offset) + 1) {\n            if(hashName(ce, deleteName.substring(offset, deleteName.length - offset)) == ceNameHash) {\n                // Check that the next closest record encloses the name one label longer\n                bytes32 checkHash = hashName(nc, deleteName.substring(lastOffset, deleteName.length - lastOffset));\n                if(ncNameHash < nc.nextHashedOwnerName) {\n                    return checkHash > ncNameHash && checkHash < nc.nextHashedOwnerName;\n                } else {\n                    return checkHash > ncNameHash || checkHash < nc.nextHashedOwnerName;\n                }\n            }\n            lastOffset = offset;\n        }\n        // If we reached the root without finding a match, return false.\n        return false;\n    }\n\n    function readNSEC3(RRUtils.SignedSet memory ss) private pure returns(RRUtils.NSEC3 memory) {\n        RRUtils.RRIterator memory iter = ss.rrs();\n        return iter.data.readNSEC3(iter.rdataOffset, iter.nextOffset - iter.rdataOffset);\n    }\n\n    function checkNSEC3Name(RRUtils.NSEC3 memory nsec, bytes memory ownerName, bytes memory deleteName) private view returns(bool) {\n        // Compute the NSEC3 name hash of the name to delete.\n        bytes32 deleteNameHash = hashName(nsec, deleteName);\n\n        // Decode the NSEC3 name hash from the first label of the NSEC3 owner name.\n        bytes32 nsecNameHash = decodeOwnerNameHash(ownerName);\n\n        return deleteNameHash == nsecNameHash;\n    }\n\n    function hashName(RRUtils.NSEC3 memory nsec, bytes memory name) private view returns(bytes32) {\n        return nsec3Digests[nsec.hashAlgorithm].hash(nsec.salt, name, nsec.iterations);\n    }\n\n    function decodeOwnerNameHash(bytes memory name) private pure returns(bytes32) {\n        return name.base32HexDecodeWord(1, uint(name.readUint8(0)));\n    }\n\n    function checkNSEC3OwnerName(bytes memory nsecName, bytes memory deleteName) private pure returns(bool) {\n        uint nsecNameOffset = nsecName.readUint8(0) + 1;\n        uint deleteNameOffset = 0;\n        while(deleteNameOffset < deleteName.length) {\n            if(deleteName.equals(deleteNameOffset, nsecName, nsecNameOffset)) {\n                return true;\n            }\n            deleteNameOffset += deleteName.readUint8(deleteNameOffset) + 1;\n        }\n        return false;\n    }\n\n    /**\n     * @dev Returns data about the RRs (if any) known to this oracle with the provided type and name.\n     * @param dnstype The DNS record type to query.\n     * @param name The name to query, in DNS label-sequence format.\n     * @return inception The unix timestamp (wrapped) at which the signature for this RRSET was created.\n     * @return expiration The unix timestamp (wrapped) at which the signature for this RRSET expires.\n     * @return hash The hash of the RRset.\n     */\n    function rrdata(uint16 dnstype, bytes calldata name) external override view returns (uint32, uint32, bytes20) {\n        RRSet storage result = rrsets[keccak256(name)][dnstype];\n        return (result.inception, result.expiration, result.hash);\n    }\n\n    function _submitRRSet(RRSetWithSignature memory input, bytes memory proof) internal returns (bytes memory) {\n        RRUtils.SignedSet memory rrset;\n        rrset = validateSignedSet(input, proof);\n\n        RRSet storage storedSet = rrsets[keccak256(rrset.name)][rrset.typeCovered];\n        if (storedSet.hash != bytes20(0)) {\n            // To replace an existing rrset, the signature must be at least as new\n            require(RRUtils.serialNumberGte(rrset.inception, storedSet.inception));\n        }\n        rrsets[keccak256(rrset.name)][rrset.typeCovered] = RRSet({\n            inception: rrset.inception,\n            expiration: rrset.expiration,\n            hash: bytes20(keccak256(rrset.data))\n        });\n\n        emit RRSetUpdated(rrset.name, rrset.data);\n\n        return rrset.data;\n    }\n\n    /**\n     * @dev Submits a signed set of RRs to the oracle.\n     *\n     * RRSETs are only accepted if they are signed with a key that is already\n     * trusted, or if they are self-signed, and the signing key is identified by\n     * a DS record that is already trusted.\n     *\n     * @param input The signed RR set. This is in the format described in section\n     *        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature\n     *        data, followed by a series of canonicalised RR records that the signature\n     *        applies to.\n     * @param proof The DNSKEY or DS to validate the signature against. Must Already\n     *        have been submitted and proved previously.\n     */\n    function validateSignedSet(RRSetWithSignature memory input, bytes memory proof) internal view returns(RRUtils.SignedSet memory rrset) {\n        rrset = input.rrset.readSignedSet();\n        require(validProof(rrset.signerName, proof));\n\n        // Do some basic checks on the RRs and extract the name\n        bytes memory name = validateRRs(rrset, rrset.typeCovered);\n        require(name.labelCount(0) == rrset.labels);\n        rrset.name = name;\n\n        // All comparisons involving the Signature Expiration and\n        // Inception fields MUST use \"serial number arithmetic\", as\n        // defined in RFC 1982\n\n        // o  The validator's notion of the current time MUST be less than or\n        //    equal to the time listed in the RRSIG RR's Expiration field.\n        require(RRUtils.serialNumberGte(rrset.expiration, uint32(block.timestamp)));\n\n        // o  The validator's notion of the current time MUST be greater than or\n        //    equal to the time listed in the RRSIG RR's Inception field.\n        require(RRUtils.serialNumberGte(uint32(block.timestamp), rrset.inception));\n\n        // Validate the signature\n        verifySignature(name, rrset, input, proof);\n\n        return rrset;\n    }\n\n    function validProof(bytes memory name, bytes memory proof) internal view returns(bool) {\n        uint16 dnstype = proof.readUint16(proof.nameLength(0));\n        return rrsets[keccak256(name)][dnstype].hash == bytes20(keccak256(proof));\n    }\n\n    /**\n     * @dev Validates a set of RRs.\n     * @param rrset The RR set.\n     * @param typecovered The type covered by the RRSIG record.\n     */\n    function validateRRs(RRUtils.SignedSet memory rrset, uint16 typecovered) internal pure returns (bytes memory name) {\n        // Iterate over all the RRs\n        for (RRUtils.RRIterator memory iter = rrset.rrs(); !iter.done(); iter.next()) {\n            // We only support class IN (Internet)\n            require(iter.class == DNSCLASS_IN);\n\n            if(name.length == 0) {\n                name = iter.name();\n            } else {\n                // Name must be the same on all RRs. We do things this way to avoid copying the name\n                // repeatedly.\n                require(name.length == iter.data.nameLength(iter.offset));\n                require(name.equals(0, iter.data, iter.offset, name.length));\n            }\n\n            // o  The RRSIG RR's Type Covered field MUST equal the RRset's type.\n            require(iter.dnstype == typecovered);\n        }\n    }\n\n    /**\n     * @dev Performs signature verification.\n     *\n     * Throws or reverts if unable to verify the record.\n     *\n     * @param name The name of the RRSIG record, in DNS label-sequence format.\n     * @param data The original data to verify.\n     * @param proof A DS or DNSKEY record that's already verified by the oracle.\n     */\n    function verifySignature(bytes memory name, RRUtils.SignedSet memory rrset, RRSetWithSignature memory data, bytes memory proof) internal view {\n        // o  The RRSIG RR's Signer's Name field MUST be the name of the zone\n        //    that contains the RRset.\n        require(rrset.signerName.length <= name.length);\n        require(rrset.signerName.equals(0, name, name.length - rrset.signerName.length));\n\n        RRUtils.RRIterator memory proofRR = proof.iterateRRs(0);\n        // Check the proof\n        if (proofRR.dnstype == DNSTYPE_DS) {\n            require(verifyWithDS(rrset, data, proofRR));\n        } else if (proofRR.dnstype == DNSTYPE_DNSKEY) {\n            require(verifyWithKnownKey(rrset, data, proofRR));\n        } else {\n            revert(\"No valid proof found\");\n        }\n    }\n\n    /**\n     * @dev Attempts to verify a signed RRSET against an already known public key.\n     * @param rrset The signed set to verify.\n     * @param data The original data the signed set was read from.\n     * @param proof The serialized DS or DNSKEY record to use as proof.\n     * @return True if the RRSET could be verified, false otherwise.\n     */\n    function verifyWithKnownKey(RRUtils.SignedSet memory rrset, RRSetWithSignature memory data, RRUtils.RRIterator memory proof) internal view returns(bool) {\n        // Check the DNSKEY's owner name matches the signer name on the RRSIG\n        require(proof.name().equals(rrset.signerName));\n        for(; !proof.done(); proof.next()) {\n            require(proof.name().equals(rrset.signerName));\n            bytes memory keyrdata = proof.rdata();\n            RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(0, keyrdata.length);\n            if(verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * @dev Attempts to verify some data using a provided key and a signature.\n     * @param dnskey The dns key record to verify the signature with.\n     * @param rrset The signed RRSET being verified.\n     * @param data The original data `rrset` was decoded from.\n     * @return True iff the key verifies the signature.\n     */\n    function verifySignatureWithKey(RRUtils.DNSKEY memory dnskey, bytes memory keyrdata, RRUtils.SignedSet memory rrset, RRSetWithSignature memory data)\n        internal\n        view\n        returns (bool)\n    {\n        // TODO: Check key isn't expired, unless updating key itself\n\n        // The Protocol Field MUST have value 3 (RFC4034 2.1.2)\n        if(dnskey.protocol != 3) {\n            return false;\n        }\n\n        // o The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST\n        //   match the owner name, algorithm, and key tag for some DNSKEY RR in\n        //   the zone's apex DNSKEY RRset.\n        if(dnskey.algorithm != rrset.algorithm) {\n            return false;\n        }\n        uint16 computedkeytag = computeKeytag(keyrdata);\n        if (computedkeytag != rrset.keytag) {\n            return false;\n        }\n\n        // o The matching DNSKEY RR MUST be present in the zone's apex DNSKEY\n        //   RRset, and MUST have the Zone Flag bit (DNSKEY RDATA Flag bit 7)\n        //   set.\n        if (dnskey.flags & DNSKEY_FLAG_ZONEKEY == 0) {\n            return false;\n        }\n\n        return algorithms[dnskey.algorithm].verify(keyrdata, data.rrset, data.sig);\n    }\n\n    /**\n     * @dev Attempts to verify a signed RRSET against an already known hash. This function assumes\n     *      that the record \n     * @param rrset The signed set to verify.\n     * @param data The original data the signed set was read from.\n     * @param proof The serialized DS or DNSKEY record to use as proof.\n     * @return True if the RRSET could be verified, false otherwise.\n     */\n    function verifyWithDS(RRUtils.SignedSet memory rrset, RRSetWithSignature memory data, RRUtils.RRIterator memory proof) internal view returns(bool) {\n        for(RRUtils.RRIterator memory iter = rrset.rrs(); !iter.done(); iter.next()) {\n            require(iter.dnstype == DNSTYPE_DNSKEY);\n            bytes memory keyrdata = iter.rdata();\n            RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(0, keyrdata.length);\n            if (verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {\n                // It's self-signed - look for a DS record to verify it.\n                return verifyKeyWithDS(iter.name(), proof, dnskey, keyrdata);\n            }\n        }\n        return false;\n    }\n\n    /**\n     * @dev Attempts to verify a key using DS records.\n     * @param keyname The DNS name of the key, in DNS label-sequence format.\n     * @param dsrrs The DS records to use in verification.\n     * @param dnskey The dnskey to verify.\n     * @param keyrdata The RDATA section of the key.\n     * @return True if a DS record verifies this key.\n     */\n    function verifyKeyWithDS(bytes memory keyname, RRUtils.RRIterator memory dsrrs, RRUtils.DNSKEY memory dnskey, bytes memory keyrdata)\n        internal view returns (bool)\n    {\n        uint16 keytag = computeKeytag(keyrdata);\n        for (; !dsrrs.done(); dsrrs.next()) {\n            RRUtils.DS memory ds = dsrrs.data.readDS(dsrrs.rdataOffset, dsrrs.nextOffset - dsrrs.rdataOffset);\n            if(ds.keytag != keytag) {\n                continue;\n            }\n            if (ds.algorithm != dnskey.algorithm) {\n                continue;\n            }\n\n            Buffer.buffer memory buf;\n            buf.init(keyname.length + keyrdata.length);\n            buf.append(keyname);\n            buf.append(keyrdata);\n            if (verifyDSHash(ds.digestType, buf.buf, ds.digest)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * @dev Attempts to verify a DS record's hash value against some data.\n     * @param digesttype The digest ID from the DS record.\n     * @param data The data to digest.\n     * @param digest The digest data to check against.\n     * @return True iff the digest matches.\n     */\n    function verifyDSHash(uint8 digesttype, bytes memory data, bytes memory digest) internal view returns (bool) {\n        if (address(digests[digesttype]) == address(0)) {\n            return false;\n        }\n        return digests[digesttype].verify(data, digest);\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        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"
    },
    "contracts/dnssec-oracle/Owned.sol": {
      "content": "pragma solidity ^0.8.4;\n\n/**\n* @dev Contract mixin for 'owned' contracts.\n*/\ncontract Owned {\n    address public owner;\n    \n    modifier owner_only() {\n        require(msg.sender == owner);\n        _;\n    }\n\n    constructor() public {\n        owner = msg.sender;\n    }\n\n    function setOwner(address newOwner) public owner_only {\n        owner = newOwner;\n    }\n}\n"
    },
    "contracts/dnssec-oracle/algorithms/Algorithm.sol": {
      "content": "pragma solidity ^0.8.4;\n\n/**\n* @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\n*/\ninterface Algorithm {\n    /**\n    * @dev Verifies a signature.\n    * @param key The public key to verify with.\n    * @param data The signed data to verify.\n    * @param signature The signature to verify.\n    * @return True iff the signature is valid.\n    */\n    function verify(bytes calldata key, bytes calldata data, bytes calldata signature) external virtual view returns (bool);\n}\n"
    },
    "contracts/dnssec-oracle/digests/Digest.sol": {
      "content": "pragma solidity ^0.8.4;\n\n/**\n* @dev An interface for contracts implementing a DNSSEC digest.\n*/\ninterface Digest {\n    /**\n    * @dev Verifies a cryptographic hash.\n    * @param data The data to hash.\n    * @param hash The hash to compare to.\n    * @return True iff the hashed data matches the provided hash value.\n    */\n    function verify(bytes calldata data, bytes calldata hash) external virtual pure returns (bool);\n}\n"
    },
    "contracts/dnssec-oracle/nsec3digests/NSEC3Digest.sol": {
      "content": "pragma solidity ^0.8.4;\n\n/**\n * @dev Interface for contracts that implement NSEC3 digest algorithms.\n */\ninterface NSEC3Digest {\n    /**\n     * @dev Performs an NSEC3 iterated hash.\n     * @param salt The salt value to use on each iteration.\n     * @param data The data to hash.\n     * @param iterations The number of iterations to perform.\n     * @return The result of the iterated hash operation.\n     */\n     function hash(bytes calldata salt, bytes calldata data, uint iterations) external virtual pure returns (bytes32);\n}\n"
    },
    "contracts/dnssec-oracle/nsec3digests/SHA1NSEC3Digest.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"./NSEC3Digest.sol\";\nimport \"../SHA1.sol\";\nimport \"@ensdomains/buffer/contracts/Buffer.sol\";\n/**\n* @dev Implements the DNSSEC iterated SHA1 digest used for NSEC3 records.\n*/\ncontract SHA1NSEC3Digest is NSEC3Digest {\n    using Buffer for Buffer.buffer;\n\n    function hash(bytes calldata salt, bytes calldata data, uint iterations) external override pure returns (bytes32) {\n        Buffer.buffer memory buf;\n        buf.init(salt.length + data.length + 16);\n\n        buf.append(data);\n        buf.append(salt);\n        bytes20 h = SHA1.sha1(buf.buf);\n        if (iterations > 0) {\n            buf.truncate();\n            buf.appendBytes20(bytes20(0));\n            buf.append(salt);\n\n            for (uint i = 0; i < iterations; i++) {\n                buf.writeBytes20(0, h);\n                h = SHA1.sha1(buf.buf);\n            }\n        }\n\n        return bytes32(h);\n    }\n}\n"
    },
    "contracts/dnssec-oracle/SHA1.sol": {
      "content": "pragma solidity >=0.8.4;\n\nlibrary SHA1 {\n    event Debug(bytes32 x);\n\n    function sha1(bytes memory data) internal pure returns(bytes20 ret) {\n        assembly {\n            // Get a safe scratch location\n            let scratch := mload(0x40)\n\n            // Get the data length, and point data at the first byte\n            let len := mload(data)\n            data := add(data, 32)\n\n            // Find the length after padding\n            let totallen := add(and(add(len, 1), 0xFFFFFFFFFFFFFFC0), 64)\n            switch lt(sub(totallen, len), 9)\n            case 1 { totallen := add(totallen, 64) }\n\n            let h := 0x6745230100EFCDAB890098BADCFE001032547600C3D2E1F0\n\n            function readword(ptr, off, count) -> result {\n                result := 0\n                if lt(off, count) {\n                    result := mload(add(ptr, off))\n                    count := sub(count, off)\n                    if lt(count, 32) {\n                        let mask := not(sub(exp(256, sub(32, count)), 1))\n                        result := and(result, mask)\n                    }\n                }\n            }\n\n            for { let i := 0 } lt(i, totallen) { i := add(i, 64) } {\n                mstore(scratch, readword(data, i, len))\n                mstore(add(scratch, 32), readword(data, add(i, 32), len))\n\n                // If we loaded the last byte, store the terminator byte\n                switch lt(sub(len, i), 64)\n                case 1 { mstore8(add(scratch, sub(len, i)), 0x80) }\n\n                // If this is the last block, store the length\n                switch eq(i, sub(totallen, 64))\n                case 1 { mstore(add(scratch, 32), or(mload(add(scratch, 32)), mul(len, 8))) }\n\n                // Expand the 16 32-bit words into 80\n                for { let j := 64 } lt(j, 128) { j := add(j, 12) } {\n                    let temp := xor(xor(mload(add(scratch, sub(j, 12))), mload(add(scratch, sub(j, 32)))), xor(mload(add(scratch, sub(j, 56))), mload(add(scratch, sub(j, 64)))))\n                    temp := or(and(mul(temp, 2), 0xFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE), and(div(temp, 0x80000000), 0x0000000100000001000000010000000100000001000000010000000100000001))\n                    mstore(add(scratch, j), temp)\n                }\n                for { let j := 128 } lt(j, 320) { j := add(j, 24) } {\n                    let temp := xor(xor(mload(add(scratch, sub(j, 24))), mload(add(scratch, sub(j, 64)))), xor(mload(add(scratch, sub(j, 112))), mload(add(scratch, sub(j, 128)))))\n                    temp := or(and(mul(temp, 4), 0xFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFC), and(div(temp, 0x40000000), 0x0000000300000003000000030000000300000003000000030000000300000003))\n                    mstore(add(scratch, j), temp)\n                }\n\n                let x := h\n                let f := 0\n                let k := 0\n                for { let j := 0 } lt(j, 80) { j := add(j, 1) } {\n                    switch div(j, 20)\n                    case 0 {\n                        // f = d xor (b and (c xor d))\n                        f := xor(div(x, 0x100000000000000000000), div(x, 0x10000000000))\n                        f := and(div(x, 0x1000000000000000000000000000000), f)\n                        f := xor(div(x, 0x10000000000), f)\n                        k := 0x5A827999\n                    }\n                    case 1{\n                        // f = b xor c xor d\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\n                        f := xor(div(x, 0x10000000000), f)\n                        k := 0x6ED9EBA1\n                    }\n                    case 2 {\n                        // f = (b and c) or (d and (b or c))\n                        f := or(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\n                        f := and(div(x, 0x10000000000), f)\n                        f := or(and(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000)), f)\n                        k := 0x8F1BBCDC\n                    }\n                    case 3 {\n                        // f = b xor c xor d\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\n                        f := xor(div(x, 0x10000000000), f)\n                        k := 0xCA62C1D6\n                    }\n                    // temp = (a leftrotate 5) + f + e + k + w[i]\n                    let temp := and(div(x, 0x80000000000000000000000000000000000000000000000), 0x1F)\n                    temp := or(and(div(x, 0x800000000000000000000000000000000000000), 0xFFFFFFE0), temp)\n                    temp := add(f, temp)\n                    temp := add(and(x, 0xFFFFFFFF), temp)\n                    temp := add(k, temp)\n                    temp := add(div(mload(add(scratch, mul(j, 4))), 0x100000000000000000000000000000000000000000000000000000000), temp)\n                    x := or(div(x, 0x10000000000), mul(temp, 0x10000000000000000000000000000000000000000))\n                    x := or(and(x, 0xFFFFFFFF00FFFFFFFF000000000000FFFFFFFF00FFFFFFFF), mul(or(and(div(x, 0x4000000000000), 0xC0000000), and(div(x, 0x400000000000000000000), 0x3FFFFFFF)), 0x100000000000000000000))\n                }\n\n                h := and(add(h, x), 0xFFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF)\n            }\n            ret := mul(or(or(or(or(and(div(h, 0x100000000), 0xFFFFFFFF00000000000000000000000000000000), and(div(h, 0x1000000), 0xFFFFFFFF000000000000000000000000)), and(div(h, 0x10000), 0xFFFFFFFF0000000000000000)), and(div(h, 0x100), 0xFFFFFFFF00000000)), and(h, 0xFFFFFFFF)), 0x1000000000000000000000000)\n        }\n    }\n}"
    },
    "contracts/dnssec-oracle/digests/SHA256Digest.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"./Digest.sol\";\nimport \"../BytesUtils.sol\";\n\n/**\n* @dev Implements the DNSSEC SHA256 digest.\n*/\ncontract SHA256Digest is Digest {\n    using BytesUtils for *;\n\n    function verify(bytes calldata data, bytes calldata hash) external override pure returns (bool) {\n        require(hash.length == 32, \"Invalid sha256 hash length\");\n        return sha256(data) == hash.readBytes32(0);\n    }\n}\n"
    },
    "contracts/dnssec-oracle/digests/SHA1Digest.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"./Digest.sol\";\nimport \"../BytesUtils.sol\";\nimport \"@ensdomains/solsha1/contracts/SHA1.sol\";\n\n/**\n* @dev Implements the DNSSEC SHA1 digest.\n*/\ncontract SHA1Digest is Digest {\n    using BytesUtils for *;\n\n    function verify(bytes calldata data, bytes calldata hash) external override pure returns (bool) {\n        require(hash.length == 20, \"Invalid sha1 hash length\");\n        bytes32 expected = hash.readBytes20(0);\n        bytes20 computed = SHA1.sha1(data);\n        return expected == computed;\n    }\n}\n"
    },
    "@ensdomains/solsha1/contracts/SHA1.sol": {
      "content": "pragma solidity ^0.8.4;\n\nlibrary SHA1 {\n    event Debug(bytes32 x);\n\n    function sha1(bytes memory data) internal pure returns(bytes20 ret) {\n        assembly {\n            // Get a safe scratch location\n            let scratch := mload(0x40)\n\n            // Get the data length, and point data at the first byte\n            let len := mload(data)\n            data := add(data, 32)\n\n            // Find the length after padding\n            let totallen := add(and(add(len, 1), 0xFFFFFFFFFFFFFFC0), 64)\n            switch lt(sub(totallen, len), 9)\n            case 1 { totallen := add(totallen, 64) }\n\n            let h := 0x6745230100EFCDAB890098BADCFE001032547600C3D2E1F0\n\n            function readword(ptr, off, count) -> result {\n                result := 0\n                if lt(off, count) {\n                    result := mload(add(ptr, off))\n                    count := sub(count, off)\n                    if lt(count, 32) {\n                        let mask := not(sub(exp(256, sub(32, count)), 1))\n                        result := and(result, mask)\n                    }\n                }\n            }\n\n            for { let i := 0 } lt(i, totallen) { i := add(i, 64) } {\n                mstore(scratch, readword(data, i, len))\n                mstore(add(scratch, 32), readword(data, add(i, 32), len))\n\n                // If we loaded the last byte, store the terminator byte\n                switch lt(sub(len, i), 64)\n                case 1 { mstore8(add(scratch, sub(len, i)), 0x80) }\n\n                // If this is the last block, store the length\n                switch eq(i, sub(totallen, 64))\n                case 1 { mstore(add(scratch, 32), or(mload(add(scratch, 32)), mul(len, 8))) }\n\n                // Expand the 16 32-bit words into 80\n                for { let j := 64 } lt(j, 128) { j := add(j, 12) } {\n                    let temp := xor(xor(mload(add(scratch, sub(j, 12))), mload(add(scratch, sub(j, 32)))), xor(mload(add(scratch, sub(j, 56))), mload(add(scratch, sub(j, 64)))))\n                    temp := or(and(mul(temp, 2), 0xFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE), and(div(temp, 0x80000000), 0x0000000100000001000000010000000100000001000000010000000100000001))\n                    mstore(add(scratch, j), temp)\n                }\n                for { let j := 128 } lt(j, 320) { j := add(j, 24) } {\n                    let temp := xor(xor(mload(add(scratch, sub(j, 24))), mload(add(scratch, sub(j, 64)))), xor(mload(add(scratch, sub(j, 112))), mload(add(scratch, sub(j, 128)))))\n                    temp := or(and(mul(temp, 4), 0xFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFC), and(div(temp, 0x40000000), 0x0000000300000003000000030000000300000003000000030000000300000003))\n                    mstore(add(scratch, j), temp)\n                }\n\n                let x := h\n                let f := 0\n                let k := 0\n                for { let j := 0 } lt(j, 80) { j := add(j, 1) } {\n                    switch div(j, 20)\n                    case 0 {\n                        // f = d xor (b and (c xor d))\n                        f := xor(div(x, 0x100000000000000000000), div(x, 0x10000000000))\n                        f := and(div(x, 0x1000000000000000000000000000000), f)\n                        f := xor(div(x, 0x10000000000), f)\n                        k := 0x5A827999\n                    }\n                    case 1{\n                        // f = b xor c xor d\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\n                        f := xor(div(x, 0x10000000000), f)\n                        k := 0x6ED9EBA1\n                    }\n                    case 2 {\n                        // f = (b and c) or (d and (b or c))\n                        f := or(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\n                        f := and(div(x, 0x10000000000), f)\n                        f := or(and(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000)), f)\n                        k := 0x8F1BBCDC\n                    }\n                    case 3 {\n                        // f = b xor c xor d\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\n                        f := xor(div(x, 0x10000000000), f)\n                        k := 0xCA62C1D6\n                    }\n                    // temp = (a leftrotate 5) + f + e + k + w[i]\n                    let temp := and(div(x, 0x80000000000000000000000000000000000000000000000), 0x1F)\n                    temp := or(and(div(x, 0x800000000000000000000000000000000000000), 0xFFFFFFE0), temp)\n                    temp := add(f, temp)\n                    temp := add(and(x, 0xFFFFFFFF), temp)\n                    temp := add(k, temp)\n                    temp := add(div(mload(add(scratch, mul(j, 4))), 0x100000000000000000000000000000000000000000000000000000000), temp)\n                    x := or(div(x, 0x10000000000), mul(temp, 0x10000000000000000000000000000000000000000))\n                    x := or(and(x, 0xFFFFFFFF00FFFFFFFF000000000000FFFFFFFF00FFFFFFFF), mul(or(and(div(x, 0x4000000000000), 0xC0000000), and(div(x, 0x400000000000000000000), 0x3FFFFFFF)), 0x100000000000000000000))\n                }\n\n                h := and(add(h, x), 0xFFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF)\n            }\n            ret := mul(or(or(or(or(and(div(h, 0x100000000), 0xFFFFFFFF00000000000000000000000000000000), and(div(h, 0x1000000), 0xFFFFFFFF000000000000000000000000)), and(div(h, 0x10000), 0xFFFFFFFF0000000000000000)), and(div(h, 0x100), 0xFFFFFFFF00000000)), and(h, 0xFFFFFFFF)), 0x1000000000000000000000000)\n        }\n    }\n}\n"
    },
    "contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"./Algorithm.sol\";\nimport \"../BytesUtils.sol\";\nimport \"./RSAVerify.sol\";\nimport \"@ensdomains/solsha1/contracts/SHA1.sol\";\n\n/**\n* @dev Implements the DNSSEC RSASHA1 algorithm.\n*/\ncontract RSASHA1Algorithm is Algorithm {\n    using BytesUtils for *;\n\n    function verify(bytes calldata key, bytes calldata data, bytes calldata sig) external override view returns (bool) {\n        bytes memory exponent;\n        bytes memory modulus;\n\n        uint16 exponentLen = uint16(key.readUint8(4));\n        if (exponentLen != 0) {\n            exponent = key.substring(5, exponentLen);\n            modulus = key.substring(exponentLen + 5, key.length - exponentLen - 5);\n        } else {\n            exponentLen = key.readUint16(5);\n            exponent = key.substring(7, exponentLen);\n            modulus = key.substring(exponentLen + 7, key.length - exponentLen - 7);\n        }\n\n        // Recover the message from the signature\n        bool ok;\n        bytes memory result;\n        (ok, result) = RSAVerify.rsarecover(modulus, exponent, sig);\n\n        // Verify it ends with the hash of our data\n        return ok && SHA1.sha1(data) == result.readBytes20(result.length - 20);\n    }\n}\n"
    },
    "contracts/dnssec-oracle/algorithms/RSAVerify.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"../BytesUtils.sol\";\nimport \"./ModexpPrecompile.sol\";\n\nlibrary RSAVerify {\n    /**\n    * @dev Recovers the input data from an RSA signature, returning the result in S.\n    * @param N The RSA public modulus.\n    * @param E The RSA public exponent.\n    * @param S The signature to recover.\n    * @return True if the recovery succeeded.\n    */\n    function rsarecover(bytes memory N, bytes memory E, bytes memory S) internal view returns (bool, bytes memory) {\n        return ModexpPrecompile.modexp(S, E, N);\n    }\n}\n"
    },
    "contracts/dnssec-oracle/algorithms/ModexpPrecompile.sol": {
      "content": "pragma solidity ^0.8.4;\n\nlibrary ModexpPrecompile {\n    /**\n    * @dev Computes (base ^ exponent) % modulus over big numbers.\n    */\n    function modexp(bytes memory base, bytes memory exponent, bytes memory modulus) internal view returns (bool success, bytes memory output) {\n        bytes memory input = abi.encodePacked(\n            uint256(base.length),\n            uint256(exponent.length),\n            uint256(modulus.length),\n            base,\n            exponent,\n            modulus\n        );\n\n        output = new bytes(modulus.length);\n\n        assembly {\n            success := staticcall(gas(), 5, add(input, 32), mload(input), add(output, 32), mload(modulus))\n        }\n    }\n}\n"
    },
    "contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"./Algorithm.sol\";\nimport \"../BytesUtils.sol\";\nimport \"./RSAVerify.sol\";\n\n/**\n* @dev Implements the DNSSEC RSASHA256 algorithm.\n*/\ncontract RSASHA256Algorithm is Algorithm {\n    using BytesUtils for *;\n\n    function verify(bytes calldata key, bytes calldata data, bytes calldata sig) external override view returns (bool) {\n        bytes memory exponent;\n        bytes memory modulus;\n\n        uint16 exponentLen = uint16(key.readUint8(4));\n        if (exponentLen != 0) {\n            exponent = key.substring(5, exponentLen);\n            modulus = key.substring(exponentLen + 5, key.length - exponentLen - 5);\n        } else {\n            exponentLen = key.readUint16(5);\n            exponent = key.substring(7, exponentLen);\n            modulus = key.substring(exponentLen + 7, key.length - exponentLen - 7);\n        }\n\n        // Recover the message from the signature\n        bool ok;\n        bytes memory result;\n        (ok, result) = RSAVerify.rsarecover(modulus, exponent, sig);\n\n        // Verify it ends with the hash of our data\n        return ok && sha256(data) == result.readBytes32(result.length - 32);\n    }\n}\n"
    },
    "contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"./Algorithm.sol\";\nimport \"./EllipticCurve.sol\";\nimport \"../BytesUtils.sol\";\n\ncontract P256SHA256Algorithm is Algorithm, EllipticCurve {\n\n    using BytesUtils for *;\n\n    /**\n    * @dev Verifies a signature.\n    * @param key The public key to verify with.\n    * @param data The signed data to verify.\n    * @param signature The signature to verify.\n    * @return True iff the signature is valid.\n    */\n    function verify(bytes calldata key, bytes calldata data, bytes calldata signature) external override view returns (bool) {\n        return validateSignature(sha256(data), parseSignature(signature), parseKey(key));\n    }\n\n    function parseSignature(bytes memory data) internal pure returns (uint256[2] memory) {\n        require(data.length == 64, \"Invalid p256 signature length\");\n        return [uint256(data.readBytes32(0)), uint256(data.readBytes32(32))];\n    }\n\n    function parseKey(bytes memory data) internal pure returns (uint256[2] memory) {\n        require(data.length == 68, \"Invalid p256 key length\");\n        return [uint256(data.readBytes32(4)), uint256(data.readBytes32(36))];\n    }\n}\n"
    },
    "contracts/dnssec-oracle/algorithms/EllipticCurve.sol": {
      "content": "pragma solidity ^0.8.4;\n\n/**\n * @title   EllipticCurve\n *\n * @author  Tilman Drerup;\n *\n * @notice  Implements elliptic curve math; Parametrized for SECP256R1.\n *\n *          Includes components of code by Andreas Olofsson, Alexander Vlasov\n *          (https://github.com/BANKEX/CurveArithmetics), and Avi Asayag\n *          (https://github.com/orbs-network/elliptic-curve-solidity)\n *\n *          Source: https://github.com/tdrerup/elliptic-curve-solidity\n *\n * @dev     NOTE: To disambiguate public keys when verifying signatures, activate\n *          condition 'rs[1] > lowSmax' in validateSignature().\n */\ncontract EllipticCurve {\n\n    // Set parameters for curve.\n    uint constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\n    uint constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\n    uint constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\n    uint constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\n    uint constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\n    uint constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\n\n    uint constant lowSmax = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0;\n\n    /**\n     * @dev Inverse of u in the field of modulo m.\n     */\n    function inverseMod(uint u, uint m) internal pure\n        returns (uint)\n    {\n        unchecked {\n            if (u == 0 || u == m || m == 0)\n                return 0;\n            if (u > m)\n                u = u % m;\n\n            int t1;\n            int t2 = 1;\n            uint r1 = m;\n            uint r2 = u;\n            uint q;\n\n            while (r2 != 0) {\n                q = r1 / r2;\n                (t1, t2, r1, r2) = (t2, t1 - int(q) * t2, r2, r1 - q * r2);\n            }\n\n            if (t1 < 0)\n                return (m - uint(-t1));\n\n            return uint(t1);\n        }\n    }\n\n    /**\n     * @dev Transform affine coordinates into projective coordinates.\n     */\n    function toProjectivePoint(uint x0, uint y0) internal pure\n        returns (uint[3] memory P)\n    {\n        P[2] = addmod(0, 1, p);\n        P[0] = mulmod(x0, P[2], p);\n        P[1] = mulmod(y0, P[2], p);\n    }\n\n    /**\n     * @dev Add two points in affine coordinates and return projective point.\n     */\n    function addAndReturnProjectivePoint(uint x1, uint y1, uint x2, uint y2) internal pure\n        returns (uint[3] memory P)\n    {\n        uint x;\n        uint y;\n        (x, y) = add(x1, y1, x2, y2);\n        P = toProjectivePoint(x, y);\n    }\n\n    /**\n     * @dev Transform from projective to affine coordinates.\n     */\n    function toAffinePoint(uint x0, uint y0, uint z0) internal pure\n        returns (uint x1, uint y1)\n    {\n        uint z0Inv;\n        z0Inv = inverseMod(z0, p);\n        x1 = mulmod(x0, z0Inv, p);\n        y1 = mulmod(y0, z0Inv, p);\n    }\n\n    /**\n     * @dev Return the zero curve in projective coordinates.\n     */\n    function zeroProj() internal pure\n        returns (uint x, uint y, uint z)\n    {\n        return (0, 1, 0);\n    }\n\n    /**\n     * @dev Return the zero curve in affine coordinates.\n     */\n    function zeroAffine() internal pure\n        returns (uint x, uint y)\n    {\n        return (0, 0);\n    }\n\n    /**\n     * @dev Check if the curve is the zero curve.\n     */\n    function isZeroCurve(uint x0, uint y0) internal pure\n        returns (bool isZero)\n    {\n        if(x0 == 0 && y0 == 0) {\n            return true;\n        }\n        return false;\n    }\n\n    /**\n     * @dev Check if a point in affine coordinates is on the curve.\n     */\n    function isOnCurve(uint x, uint y) internal pure\n        returns (bool)\n    {\n        if (0 == x || x == p || 0 == y || y == p) {\n            return false;\n        }\n\n        uint LHS = mulmod(y, y, p); // y^2\n        uint RHS = mulmod(mulmod(x, x, p), x, p); // x^3\n\n        if (a != 0) {\n            RHS = addmod(RHS, mulmod(x, a, p), p); // x^3 + a*x\n        }\n        if (b != 0) {\n            RHS = addmod(RHS, b, p); // x^3 + a*x + b\n        }\n\n        return LHS == RHS;\n    }\n\n    /**\n     * @dev Double an elliptic curve point in projective coordinates. See\n     * https://www.nayuki.io/page/elliptic-curve-point-addition-in-projective-coordinates\n     */\n    function twiceProj(uint x0, uint y0, uint z0) internal pure\n        returns (uint x1, uint y1, uint z1)\n    {\n        uint t;\n        uint u;\n        uint v;\n        uint w;\n\n        if(isZeroCurve(x0, y0)) {\n            return zeroProj();\n        }\n\n        u = mulmod(y0, z0, p);\n        u = mulmod(u, 2, p);\n\n        v = mulmod(u, x0, p);\n        v = mulmod(v, y0, p);\n        v = mulmod(v, 2, p);\n\n        x0 = mulmod(x0, x0, p);\n        t = mulmod(x0, 3, p);\n\n        z0 = mulmod(z0, z0, p);\n        z0 = mulmod(z0, a, p);\n        t = addmod(t, z0, p);\n\n        w = mulmod(t, t, p);\n        x0 = mulmod(2, v, p);\n        w = addmod(w, p-x0, p);\n\n        x0 = addmod(v, p-w, p);\n        x0 = mulmod(t, x0, p);\n        y0 = mulmod(y0, u, p);\n        y0 = mulmod(y0, y0, p);\n        y0 = mulmod(2, y0, p);\n        y1 = addmod(x0, p-y0, p);\n\n        x1 = mulmod(u, w, p);\n\n        z1 = mulmod(u, u, p);\n        z1 = mulmod(z1, u, p);\n    }\n\n    /**\n     * @dev Add two elliptic curve points in projective coordinates. See\n     * https://www.nayuki.io/page/elliptic-curve-point-addition-in-projective-coordinates\n     */\n    function addProj(uint x0, uint y0, uint z0, uint x1, uint y1, uint z1) internal pure\n        returns (uint x2, uint y2, uint z2)\n    {\n        uint t0;\n        uint t1;\n        uint u0;\n        uint u1;\n\n        if (isZeroCurve(x0, y0)) {\n            return (x1, y1, z1);\n        }\n        else if (isZeroCurve(x1, y1)) {\n            return (x0, y0, z0);\n        }\n\n        t0 = mulmod(y0, z1, p);\n        t1 = mulmod(y1, z0, p);\n\n        u0 = mulmod(x0, z1, p);\n        u1 = mulmod(x1, z0, p);\n\n        if (u0 == u1) {\n            if (t0 == t1) {\n                return twiceProj(x0, y0, z0);\n            }\n            else {\n                return zeroProj();\n            }\n        }\n\n        (x2, y2, z2) = addProj2(mulmod(z0, z1, p), u0, u1, t1, t0);\n    }\n\n    /**\n     * @dev Helper function that splits addProj to avoid too many local variables.\n     */\n    function addProj2(uint v, uint u0, uint u1, uint t1, uint t0) private pure\n        returns (uint x2, uint y2, uint z2)\n    {\n        uint u;\n        uint u2;\n        uint u3;\n        uint w;\n        uint t;\n\n        t = addmod(t0, p-t1, p);\n        u = addmod(u0, p-u1, p);\n        u2 = mulmod(u, u, p);\n\n        w = mulmod(t, t, p);\n        w = mulmod(w, v, p);\n        u1 = addmod(u1, u0, p);\n        u1 = mulmod(u1, u2, p);\n        w = addmod(w, p-u1, p);\n\n        x2 = mulmod(u, w, p);\n\n        u3 = mulmod(u2, u, p);\n        u0 = mulmod(u0, u2, p);\n        u0 = addmod(u0, p-w, p);\n        t = mulmod(t, u0, p);\n        t0 = mulmod(t0, u3, p);\n\n        y2 = addmod(t, p-t0, p);\n\n        z2 = mulmod(u3, v, p);\n    }\n\n    /**\n     * @dev Add two elliptic curve points in affine coordinates.\n     */\n    function add(uint x0, uint y0, uint x1, uint y1) internal pure\n        returns (uint, uint)\n    {\n        uint z0;\n\n        (x0, y0, z0) = addProj(x0, y0, 1, x1, y1, 1);\n\n        return toAffinePoint(x0, y0, z0);\n    }\n\n    /**\n     * @dev Double an elliptic curve point in affine coordinates.\n     */\n    function twice(uint x0, uint y0) internal pure\n        returns (uint, uint)\n    {\n        uint z0;\n\n        (x0, y0, z0) = twiceProj(x0, y0, 1);\n\n        return toAffinePoint(x0, y0, z0);\n    }\n\n    /**\n     * @dev Multiply an elliptic curve point by a 2 power base (i.e., (2^exp)*P)).\n     */\n    function multiplyPowerBase2(uint x0, uint y0, uint exp) internal pure\n        returns (uint, uint)\n    {\n        uint base2X = x0;\n        uint base2Y = y0;\n        uint base2Z = 1;\n\n        for(uint i = 0; i < exp; i++) {\n            (base2X, base2Y, base2Z) = twiceProj(base2X, base2Y, base2Z);\n        }\n\n        return toAffinePoint(base2X, base2Y, base2Z);\n    }\n\n    /**\n     * @dev Multiply an elliptic curve point by a scalar.\n     */\n    function multiplyScalar(uint x0, uint y0, uint scalar) internal pure\n        returns (uint x1, uint y1)\n    {\n        if(scalar == 0) {\n            return zeroAffine();\n        }\n        else if (scalar == 1) {\n            return (x0, y0);\n        }\n        else if (scalar == 2) {\n            return twice(x0, y0);\n        }\n\n        uint base2X = x0;\n        uint base2Y = y0;\n        uint base2Z = 1;\n        uint z1 = 1;\n        x1 = x0;\n        y1 = y0;\n\n        if(scalar%2 == 0) {\n            x1 = y1 = 0;\n        }\n\n        scalar = scalar >> 1;\n\n        while(scalar > 0) {\n            (base2X, base2Y, base2Z) = twiceProj(base2X, base2Y, base2Z);\n\n            if(scalar%2 == 1) {\n                (x1, y1, z1) = addProj(base2X, base2Y, base2Z, x1, y1, z1);\n            }\n\n            scalar = scalar >> 1;\n        }\n\n        return toAffinePoint(x1, y1, z1);\n    }\n\n    /**\n     * @dev Multiply the curve's generator point by a scalar.\n     */\n    function multipleGeneratorByScalar(uint scalar) internal pure\n        returns (uint, uint)\n    {\n        return multiplyScalar(gx, gy, scalar);\n    }\n\n    /**\n     * @dev Validate combination of message, signature, and public key.\n     */\n    function validateSignature(bytes32 message, uint[2] memory rs, uint[2] memory Q) internal pure\n        returns (bool)\n    {\n\n        // To disambiguate between public key solutions, include comment below.\n        if(rs[0] == 0 || rs[0] >= n || rs[1] == 0) {// || rs[1] > lowSmax)\n            return false;\n        }\n        if (!isOnCurve(Q[0], Q[1])) {\n            return false;\n        }\n\n        uint x1;\n        uint x2;\n        uint y1;\n        uint y2;\n\n        uint sInv = inverseMod(rs[1], n);\n        (x1, y1) = multiplyScalar(gx, gy, mulmod(uint(message), sInv, n));\n        (x2, y2) = multiplyScalar(Q[0], Q[1], mulmod(rs[0], sInv, n));\n        uint[3] memory P = addAndReturnProjectivePoint(x1, y1, x2, y2);\n\n        if (P[2] == 0) {\n            return false;\n        }\n\n        uint Px = inverseMod(P[2], p);\n        Px = mulmod(P[0], mulmod(Px, Px, p), p);\n\n        return Px % n == rs[0];\n    }\n}"
    },
    "contracts/dnssec-oracle/algorithms/DummyAlgorithm.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"./Algorithm.sol\";\n\n/**\n* @dev Implements a dummy DNSSEC (signing) algorithm that approves all\n*      signatures, for testing.\n*/\ncontract DummyAlgorithm is Algorithm {\n    function verify(bytes calldata, bytes calldata, bytes calldata) external override view returns (bool) { return true; }\n}\n"
    },
    "contracts/dnssec-oracle/digests/DummyDigest.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"./Digest.sol\";\n\n/**\n* @dev Implements a dummy DNSSEC digest that approves all hashes, for testing.\n*/\ncontract DummyDigest is Digest {\n    function verify(bytes calldata, bytes calldata) external override pure returns (bool) { return true; }\n}\n"
    },
    "contracts/ethregistrar/mocks/DummyDNSSEC.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"../../registry/ENSRegistry.sol\";\nimport \"../../dnssec-oracle/DNSSEC.sol\";\n\ncontract DummyDnsRegistrarDNSSEC {\n\n    struct Data {\n        uint32 inception;\n        uint64 inserted;\n        bytes20 hash;\n    }\n\n    mapping (bytes32 => Data) private datas;\n\n    function setData(uint16 _expectedType, bytes memory _expectedName, uint32 _inception, uint64 _inserted, bytes memory _proof) public {\n        Data storage rr = datas[keccak256(abi.encodePacked(_expectedType, _expectedName))];\n        rr.inception = _inception;\n        rr.inserted = _inserted;\n\n        if (_proof.length != 0) {\n            rr.hash = bytes20(keccak256(_proof));\n        } else {\n            rr.hash = bytes20(0);\n        }\n    }\n\n    function rrdata(uint16 dnstype, bytes memory name) public view returns (uint32, uint64, bytes20) {\n        Data storage rr = datas[keccak256(abi.encodePacked(dnstype, name))];\n        return (rr.inception, rr.inserted, rr.hash);\n    }\n\n    function submitRRSets(DNSSEC.RRSetWithSignature[] memory input, bytes calldata) public virtual returns (bytes memory) {\n        return input[input.length - 1].rrset;\n    }\n}\n"
    },
    "contracts/registry/ENSRegistryWithFallback.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"./ENS.sol\";\nimport \"./ENSRegistry.sol\";\n\n/**\n * The ENS registry contract.\n */\ncontract ENSRegistryWithFallback is ENSRegistry {\n\n    ENS public old;\n\n    /**\n     * @dev Constructs a new ENS registrar.\n     */\n    constructor(ENS _old) public ENSRegistry() {\n        old = _old;\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(bytes32 node) public override view returns (address) {\n        if (!recordExists(node)) {\n            return old.resolver(node);\n        }\n\n        return super.resolver(node);\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(bytes32 node) public override view returns (address) {\n        if (!recordExists(node)) {\n            return old.owner(node);\n        }\n\n        return super.owner(node);\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 override view returns (uint64) {\n        if (!recordExists(node)) {\n            return old.ttl(node);\n        }\n\n        return super.ttl(node);\n    }\n\n    function _setOwner(bytes32 node, address owner) internal override {\n        address addr = owner;\n        if (addr == address(0x0)) {\n            addr = address(this);\n        }\n\n        super._setOwner(node, addr);\n    }\n}\n"
    },
    "contracts/registry/ReverseRegistrar.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"./ENS.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../root/Controllable.sol\";\n\nabstract contract NameResolver {\n    function setName(bytes32 node, string memory name) public virtual;\n}\n\nbytes32 constant lookup = 0x3031323334353637383961626364656600000000000000000000000000000000;\n\nbytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;\n\n// namehash('addr.reverse')\n\ncontract ReverseRegistrar is Ownable, Controllable {\n    ENS public ens;\n    NameResolver public defaultResolver;\n\n    event ReverseClaimed(address indexed addr, bytes32 indexed node);\n\n    /**\n     * @dev Constructor\n     * @param ensAddr The address of the ENS registry.\n     * @param resolverAddr The address of the default reverse resolver.\n     */\n    constructor(ENS ensAddr, NameResolver resolverAddr) {\n        ens = ensAddr;\n        defaultResolver = resolverAddr;\n\n        // Assign ownership of the reverse record to our deployer\n        ReverseRegistrar oldRegistrar = ReverseRegistrar(\n            ens.owner(ADDR_REVERSE_NODE)\n        );\n        if (address(oldRegistrar) != address(0x0)) {\n            oldRegistrar.claim(msg.sender);\n        }\n    }\n\n    modifier authorised(address addr) {\n        require(\n            addr == msg.sender ||\n                controllers[msg.sender] ||\n                ens.isApprovedForAll(addr, msg.sender) ||\n                ownsContract(addr),\n            \"Caller is not a controller or authorised by address or the address itself\"\n        );\n        _;\n    }\n\n    /**\n     * @dev Transfers ownership of the reverse ENS record associated with the\n     *      calling account.\n     * @param owner The address to set as the owner of the reverse record in ENS.\n     * @return The ENS node hash of the reverse record.\n     */\n    function claim(address owner) public returns (bytes32) {\n        return _claimWithResolver(msg.sender, owner, address(0x0));\n    }\n\n    /**\n     * @dev Transfers ownership of the reverse ENS record associated with the\n     *      calling account.\n     * @param addr The reverse record to set\n     * @param owner The address to set as the owner of the reverse record in ENS.\n     * @return The ENS node hash of the reverse record.\n     */\n    function claimForAddr(address addr, address owner)\n        public\n        authorised(addr)\n        returns (bytes32)\n    {\n        return _claimWithResolver(addr, owner, address(0x0));\n    }\n\n    /**\n     * @dev Transfers ownership of the reverse ENS record associated with the\n     *      calling account.\n     * @param owner The address to set as the owner of the reverse record in ENS.\n     * @param resolver The address of the resolver to set; 0 to leave unchanged.\n     * @return The ENS node hash of the reverse record.\n     */\n    function claimWithResolver(address owner, address resolver)\n        public\n        returns (bytes32)\n    {\n        return _claimWithResolver(msg.sender, owner, resolver);\n    }\n\n    /**\n     * @dev Transfers ownership of the reverse ENS record specified with the\n     *      address provided\n     * @param addr The reverse record to set\n     * @param owner The address to set as the owner of the reverse record in ENS.\n     * @param resolver The address of the resolver to set; 0 to leave unchanged.\n     * @return The ENS node hash of the reverse record.\n     */\n    function claimWithResolverForAddr(\n        address addr,\n        address owner,\n        address resolver\n    ) public authorised(addr) returns (bytes32) {\n        return _claimWithResolver(addr, owner, resolver);\n    }\n\n    /**\n     * @dev Sets the `name()` record for the reverse ENS record associated with\n     * the calling account. First updates the resolver to the default reverse\n     * resolver if necessary.\n     * @param name The name to set for this address.\n     * @return The ENS node hash of the reverse record.\n     */\n    function setName(string memory name) public returns (bytes32) {\n        bytes32 node = _claimWithResolver(\n            msg.sender,\n            address(this),\n            address(defaultResolver)\n        );\n        defaultResolver.setName(node, name);\n        return node;\n    }\n\n    /**\n     * @dev Sets the `name()` record for the reverse ENS record associated with\n     * the account provided. First updates the resolver to the default reverse\n     * resolver if necessary.\n     * Only callable by controllers and authorised users\n     * @param addr The reverse record to set\n     * @param owner The owner of the reverse node\n     * @param name The name to set for this address.\n     * @return The ENS node hash of the reverse record.\n     */\n    function setNameForAddr(\n        address addr,\n        address owner,\n        string memory name\n    ) public authorised(addr) returns (bytes32) {\n        bytes32 node = _claimWithResolver(\n            addr,\n            address(this),\n            address(defaultResolver)\n        );\n        defaultResolver.setName(node, name);\n        ens.setSubnodeOwner(ADDR_REVERSE_NODE, sha3HexAddress(addr), owner);\n        return node;\n    }\n\n    /**\n     * @dev Returns the node hash for a given account's reverse records.\n     * @param addr The address to hash\n     * @return The ENS node hash.\n     */\n    function node(address addr) public pure returns (bytes32) {\n        return\n            keccak256(\n                abi.encodePacked(ADDR_REVERSE_NODE, sha3HexAddress(addr))\n            );\n    }\n\n    /**\n     * @dev An optimised function to compute the sha3 of the lower-case\n     *      hexadecimal representation of an Ethereum address.\n     * @param addr The address to hash\n     * @return ret The SHA3 hash of the lower-case hexadecimal encoding of the\n     *         input address.\n     */\n    function sha3HexAddress(address addr) private pure returns (bytes32 ret) {\n        assembly {\n            for {\n                let i := 40\n            } gt(i, 0) {\n\n            } {\n                i := sub(i, 1)\n                mstore8(i, byte(and(addr, 0xf), lookup))\n                addr := div(addr, 0x10)\n                i := sub(i, 1)\n                mstore8(i, byte(and(addr, 0xf), lookup))\n                addr := div(addr, 0x10)\n            }\n\n            ret := keccak256(0, 40)\n        }\n    }\n\n    /* Internal functions */\n\n    function _claimWithResolver(\n        address addr,\n        address owner,\n        address resolver\n    ) internal returns (bytes32) {\n        bytes32 label = sha3HexAddress(addr);\n        bytes32 node = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));\n        address currentResolver = ens.resolver(node);\n        bool shouldUpdateResolver = (resolver != address(0x0) &&\n            resolver != currentResolver);\n        address newResolver = shouldUpdateResolver ? resolver : currentResolver;\n\n        ens.setSubnodeRecord(ADDR_REVERSE_NODE, label, owner, newResolver, 0);\n\n        emit ReverseClaimed(addr, node);\n\n        return node;\n    }\n\n    function ownsContract(address addr) internal view returns (bool) {\n        try Ownable(addr).owner() returns (address owner) {\n            return owner == msg.sender;\n        } catch {\n            return false;\n        }\n    }\n}\n"
    },
    "contracts/ethregistrar/StablePriceOracle.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"./PriceOracle.sol\";\nimport \"./SafeMath.sol\";\nimport \"./StringUtils.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface AggregatorInterface {\n  function latestAnswer() external view returns (int256);\n}\n\n\n// StablePriceOracle sets a price in USD, based on an oracle.\ncontract StablePriceOracle is Ownable, PriceOracle {\n    using SafeMath for *;\n    using StringUtils for *;\n\n    // Rent in base price units by length. Element 0 is for 1-length names, and so on.\n    uint[] public rentPrices;\n\n    // Oracle address\n    AggregatorInterface public usdOracle;\n\n    event OracleChanged(address oracle);\n\n    event RentPriceChanged(uint[] prices);\n\n    bytes4 constant private INTERFACE_META_ID = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n    bytes4 constant private ORACLE_ID = bytes4(keccak256(\"price(string,uint256,uint256)\") ^ keccak256(\"premium(string,uint256,uint256)\"));\n\n    constructor(AggregatorInterface _usdOracle, uint[] memory _rentPrices) public {\n        usdOracle = _usdOracle;\n        setPrices(_rentPrices);\n    }\n\n    function price(string calldata name, uint expires, uint duration) external view override returns(uint) {\n        uint len = name.strlen();\n        if(len > rentPrices.length) {\n            len = rentPrices.length;\n        }\n        require(len > 0);\n        \n        uint basePrice = rentPrices[len - 1].mul(duration);\n        basePrice = basePrice.add(_premium(name, expires, duration));\n\n        return attoUSDToWei(basePrice);\n    }\n\n    /**\n     * @dev Sets rent prices.\n     * @param _rentPrices The price array. Each element corresponds to a specific\n     *                    name length; names longer than the length of the array\n     *                    default to the price of the last element. Values are\n     *                    in base price units, equal to one attodollar (1e-18\n     *                    dollar) each.\n     */\n    function setPrices(uint[] memory _rentPrices) public onlyOwner {\n        rentPrices = _rentPrices;\n        emit RentPriceChanged(_rentPrices);\n    }\n\n    /**\n     * @dev Sets the price oracle address\n     * @param _usdOracle The address of the price oracle to use.\n     */\n    function setOracle(AggregatorInterface _usdOracle) public onlyOwner {\n        usdOracle = _usdOracle;\n        emit OracleChanged(address(_usdOracle));\n    }\n\n    /**\n     * @dev Returns the pricing premium in wei.\n     */\n    function premium(string calldata name, uint expires, uint duration) external view returns(uint) {\n        return attoUSDToWei(_premium(name, expires, duration));\n    }\n\n    /**\n     * @dev Returns the pricing premium in internal base units.\n     */\n    function _premium(string memory name, uint expires, uint duration) virtual internal view returns(uint) {\n        return 0;\n    }\n\n    function attoUSDToWei(uint amount) internal view returns(uint) {\n        uint ethPrice = uint(usdOracle.latestAnswer());\n        return amount.mul(1e8).div(ethPrice);\n    }\n\n    function weiToAttoUSD(uint amount) internal view returns(uint) {\n        uint ethPrice = uint(usdOracle.latestAnswer());\n        return amount.mul(ethPrice).div(1e8);\n    }\n\n    function supportsInterface(bytes4 interfaceID) public view virtual returns (bool) {\n        return interfaceID == INTERFACE_META_ID || interfaceID == ORACLE_ID;\n    }\n}\n"
    },
    "contracts/ethregistrar/PriceOracle.sol": {
      "content": "pragma solidity >=0.8.4;\n\ninterface PriceOracle {\n    /**\n     * @dev Returns the price to register or renew a name.\n     * @param name The name being registered or renewed.\n     * @param expires When the name presently expires (0 if this is a new registration).\n     * @param duration How long the name is being registered or extended for, in seconds.\n     * @return The price of this renewal or registration, in wei.\n     */\n    function price(string calldata name, uint expires, uint duration) external view returns(uint);\n}\n"
    },
    "contracts/ethregistrar/SafeMath.sol": {
      "content": "pragma solidity >=0.8.4;\n\n/**\n * @title SafeMath\n * @dev Unsigned math operations with safety checks that revert on error\n */\nlibrary SafeMath {\n    /**\n    * @dev Multiplies two unsigned integers, reverts on overflow.\n    */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n        // benefit is lost if 'b' is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522\n        if (a == 0) {\n            return 0;\n        }\n\n        uint256 c = a * b;\n        require(c / a == b);\n\n        return c;\n    }\n\n    /**\n    * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.\n    */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        // Solidity only automatically asserts when dividing by 0\n        require(b > 0);\n        uint256 c = a / b;\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n        return c;\n    }\n\n    /**\n    * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).\n    */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b <= a);\n        uint256 c = a - b;\n\n        return c;\n    }\n\n    /**\n    * @dev Adds two unsigned integers, reverts on overflow.\n    */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 c = a + b;\n        require(c >= a);\n\n        return c;\n    }\n\n    /**\n    * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),\n    * reverts when dividing by zero.\n    */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b != 0);\n        return a % b;\n    }\n}\n"
    },
    "contracts/ethregistrar/StringUtils.sol": {
      "content": "pragma solidity >=0.8.4;\n\nlibrary StringUtils {\n    /**\n     * @dev Returns the length of a given string\n     *\n     * @param s The string to measure the length of\n     * @return The length of the input string\n     */\n    function strlen(string memory s) internal pure returns (uint) {\n        uint len;\n        uint i = 0;\n        uint bytelength = bytes(s).length;\n        for(len = 0; i < bytelength; len++) {\n            bytes1 b = bytes(s)[i];\n            if(b < 0x80) {\n                i += 1;\n            } else if (b < 0xE0) {\n                i += 2;\n            } else if (b < 0xF0) {\n                i += 3;\n            } else if (b < 0xF8) {\n                i += 4;\n            } else if (b < 0xFC) {\n                i += 5;\n            } else {\n                i += 6;\n            }\n        }\n        return len;\n    }\n}\n"
    },
    "contracts/ethregistrar/ETHRegistrarController.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"./PriceOracle.sol\";\nimport \"./BaseRegistrarImplementation.sol\";\nimport \"./StringUtils.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../resolvers/Resolver.sol\";\n\n/**\n * @dev A registrar controller for registering and renewing names at fixed cost.\n */\ncontract ETHRegistrarController is Ownable {\n    using StringUtils for *;\n\n    uint constant public MIN_REGISTRATION_DURATION = 28 days;\n\n    bytes4 constant private INTERFACE_META_ID = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n    bytes4 constant private COMMITMENT_CONTROLLER_ID = bytes4(\n        keccak256(\"rentPrice(string,uint256)\") ^\n        keccak256(\"available(string)\") ^\n        keccak256(\"makeCommitment(string,address,bytes32)\") ^\n        keccak256(\"commit(bytes32)\") ^\n        keccak256(\"register(string,address,uint256,bytes32)\") ^\n        keccak256(\"renew(string,uint256)\")\n    );\n\n    bytes4 constant private COMMITMENT_WITH_CONFIG_CONTROLLER_ID = bytes4(\n        keccak256(\"registerWithConfig(string,address,uint256,bytes32,address,address)\") ^\n        keccak256(\"makeCommitmentWithConfig(string,address,bytes32,address,address)\")\n    );\n\n    BaseRegistrarImplementation base;\n    PriceOracle prices;\n    uint public minCommitmentAge;\n    uint public maxCommitmentAge;\n\n    mapping(bytes32=>uint) public commitments;\n\n    event NameRegistered(string name, bytes32 indexed label, address indexed owner, uint cost, uint expires);\n    event NameRenewed(string name, bytes32 indexed label, uint cost, uint expires);\n    event NewPriceOracle(address indexed oracle);\n\n    constructor(BaseRegistrarImplementation _base, PriceOracle _prices, uint _minCommitmentAge, uint _maxCommitmentAge) public {\n        require(_maxCommitmentAge > _minCommitmentAge);\n\n        base = _base;\n        prices = _prices;\n        minCommitmentAge = _minCommitmentAge;\n        maxCommitmentAge = _maxCommitmentAge;\n    }\n\n    function rentPrice(string memory name, uint duration) view public returns(uint) {\n        bytes32 hash = keccak256(bytes(name));\n        return prices.price(name, base.nameExpires(uint256(hash)), duration);\n    }\n\n    function valid(string memory name) public pure returns(bool) {\n        return name.strlen() >= 3;\n    }\n\n    function available(string memory name) public view returns(bool) {\n        bytes32 label = keccak256(bytes(name));\n        return valid(name) && base.available(uint256(label));\n    }\n\n    function makeCommitment(string memory name, address owner, bytes32 secret) pure public returns(bytes32) {\n        return makeCommitmentWithConfig(name, owner, secret, address(0), address(0));\n    }\n\n    function makeCommitmentWithConfig(string memory name, address owner, bytes32 secret, address resolver, address addr) pure public returns(bytes32) {\n        bytes32 label = keccak256(bytes(name));\n        if (resolver == address(0) && addr == address(0)) {\n            return keccak256(abi.encodePacked(label, owner, secret));\n        }\n        require(resolver != address(0));\n        return keccak256(abi.encodePacked(label, owner, resolver, addr, secret));\n    }\n\n    function commit(bytes32 commitment) public {\n        require(commitments[commitment] + maxCommitmentAge < block.timestamp);\n        commitments[commitment] = block.timestamp;\n    }\n\n    function register(string calldata name, address owner, uint duration, bytes32 secret) external payable {\n      registerWithConfig(name, owner, duration, secret, address(0), address(0));\n    }\n\n    function registerWithConfig(string memory name, address owner, uint duration, bytes32 secret, address resolver, address addr) public payable {\n        bytes32 commitment = makeCommitmentWithConfig(name, owner, secret, resolver, addr);\n        uint cost = _consumeCommitment(name, duration, commitment);\n\n        bytes32 label = keccak256(bytes(name));\n        uint256 tokenId = uint256(label);\n\n        uint expires;\n        if(resolver != address(0)) {\n            // Set this contract as the (temporary) owner, giving it\n            // permission to set up the resolver.\n            expires = base.register(tokenId, address(this), duration);\n\n            // The nodehash of this label\n            bytes32 nodehash = keccak256(abi.encodePacked(base.baseNode(), label));\n\n            // Set the resolver\n            base.ens().setResolver(nodehash, resolver);\n\n            // Configure the resolver\n            if (addr != address(0)) {\n                Resolver(resolver).setAddr(nodehash, addr);\n            }\n\n            // Now transfer full ownership to the expeceted owner\n            base.reclaim(tokenId, owner);\n            base.transferFrom(address(this), owner, tokenId);\n        } else {\n            require(addr == address(0));\n            expires = base.register(tokenId, owner, duration);\n        }\n\n        emit NameRegistered(name, label, owner, cost, expires);\n\n        // Refund any extra payment\n        if(msg.value > cost) {\n            payable(msg.sender).transfer(msg.value - cost);\n        }\n    }\n\n    function renew(string calldata name, uint duration) external payable {\n        uint cost = rentPrice(name, duration);\n        require(msg.value >= cost);\n\n        bytes32 label = keccak256(bytes(name));\n        uint expires = base.renew(uint256(label), duration);\n\n        if(msg.value > cost) {\n            payable(msg.sender).transfer(msg.value - cost);\n        }\n\n        emit NameRenewed(name, label, cost, expires);\n    }\n\n    function setPriceOracle(PriceOracle _prices) public onlyOwner {\n        prices = _prices;\n        emit NewPriceOracle(address(prices));\n    }\n\n    function setCommitmentAges(uint _minCommitmentAge, uint _maxCommitmentAge) public onlyOwner {\n        minCommitmentAge = _minCommitmentAge;\n        maxCommitmentAge = _maxCommitmentAge;\n    }\n\n    function withdraw() public onlyOwner {\n        payable(msg.sender).transfer(address(this).balance);        \n    }\n\n    function supportsInterface(bytes4 interfaceID) external pure returns (bool) {\n        return interfaceID == INTERFACE_META_ID ||\n               interfaceID == COMMITMENT_CONTROLLER_ID ||\n               interfaceID == COMMITMENT_WITH_CONFIG_CONTROLLER_ID;\n    }\n\n    function _consumeCommitment(string memory name, uint duration, bytes32 commitment) internal returns (uint256) {\n        // Require a valid commitment\n        require(commitments[commitment] + minCommitmentAge <= block.timestamp);\n\n        // If the commitment is too old, or the name is registered, stop\n        require(commitments[commitment] + maxCommitmentAge > block.timestamp);\n        require(available(name));\n\n        delete(commitments[commitment]);\n\n        uint cost = rentPrice(name, duration);\n        require(duration >= MIN_REGISTRATION_DURATION);\n        require(msg.value >= cost);\n\n        return cost;\n    }\n}\n"
    },
    "contracts/ethregistrar/BaseRegistrarImplementation.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"../registry/ENS.sol\";\nimport \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\n\nimport \"./BaseRegistrar.sol\";\ncontract BaseRegistrarImplementation is ERC721, BaseRegistrar  {\n    // A map of expiry times\n    mapping(uint256=>uint) expiries;\n\n    bytes4 constant private INTERFACE_META_ID = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n    bytes4 constant private ERC721_ID = bytes4(\n        keccak256(\"balanceOf(address)\") ^\n        keccak256(\"ownerOf(uint256)\") ^\n        keccak256(\"approve(address,uint256)\") ^\n        keccak256(\"getApproved(uint256)\") ^\n        keccak256(\"setApprovalForAll(address,bool)\") ^\n        keccak256(\"isApprovedForAll(address,address)\") ^\n        keccak256(\"transferFrom(address,address,uint256)\") ^\n        keccak256(\"safeTransferFrom(address,address,uint256)\") ^\n        keccak256(\"safeTransferFrom(address,address,uint256,bytes)\")\n    );\n    bytes4 constant private RECLAIM_ID = bytes4(keccak256(\"reclaim(uint256,address)\"));\n\n    /**\n     * v2.1.3 version of _isApprovedOrOwner which calls ownerOf(tokenId) and takes grace period into consideration instead of ERC721.ownerOf(tokenId);\n     * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.1.3/contracts/token/ERC721/ERC721.sol#L187\n     * @dev Returns whether the given spender can transfer a given token ID\n     * @param spender address of the spender to query\n     * @param tokenId uint256 ID of the token to be transferred\n     * @return bool whether the msg.sender is approved for the given token ID,\n     *    is an operator of the owner, or is the owner of the token\n     */\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view override returns (bool) {\n        address owner = ownerOf(tokenId);\n        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));\n    }\n\n    constructor(ENS _ens, bytes32 _baseNode) ERC721(\"\",\"\") {\n        ens = _ens;\n        baseNode = _baseNode;\n    }\n\n    modifier live {\n        require(ens.owner(baseNode) == address(this));\n        _;\n    }\n\n    modifier onlyController {\n        require(controllers[msg.sender]);\n        _;\n    }\n\n    /**\n     * @dev Gets the owner of the specified token ID. Names become unowned\n     *      when their registration expires.\n     * @param tokenId uint256 ID of the token to query the owner of\n     * @return address currently marked as the owner of the given token ID\n     */\n    function ownerOf(uint256 tokenId) public view override(IERC721, ERC721) returns (address) {\n        require(expiries[tokenId] > block.timestamp);\n        return super.ownerOf(tokenId);\n    }\n\n    // Authorises a controller, who can register and renew domains.\n    function addController(address controller) external override onlyOwner {\n        controllers[controller] = true;\n        emit ControllerAdded(controller);\n    }\n\n    // Revoke controller permission for an address.\n    function removeController(address controller) external override onlyOwner {\n        controllers[controller] = false;\n        emit ControllerRemoved(controller);\n    }\n\n    // Set the resolver for the TLD this registrar manages.\n    function setResolver(address resolver) external override onlyOwner {\n        ens.setResolver(baseNode, resolver);\n    }\n\n    // Returns the expiration timestamp of the specified id.\n    function nameExpires(uint256 id) external view override returns(uint) {\n        return expiries[id];\n    }\n\n    // Returns true iff the specified name is available for registration.\n    function available(uint256 id) public view override returns(bool) {\n        // Not available if it's registered here or in its grace period.\n        return expiries[id] + GRACE_PERIOD < block.timestamp;\n    }\n\n    /**\n     * @dev Register a name.\n     * @param id The token ID (keccak256 of the label).\n     * @param owner The address that should own the registration.\n     * @param duration Duration in seconds for the registration.\n     */\n    function register(uint256 id, address owner, uint duration) external override returns(uint) {\n      return _register(id, owner, duration, true);\n    }\n\n    /**\n     * @dev Register a name, without modifying the registry.\n     * @param id The token ID (keccak256 of the label).\n     * @param owner The address that should own the registration.\n     * @param duration Duration in seconds for the registration.\n     */\n    function registerOnly(uint256 id, address owner, uint duration) external returns(uint) {\n      return _register(id, owner, duration, false);\n    }\n\n    function _register(uint256 id, address owner, uint duration, bool updateRegistry) internal live onlyController returns(uint) {\n        require(available(id));\n        require(block.timestamp + duration + GRACE_PERIOD > block.timestamp + GRACE_PERIOD); // Prevent future overflow\n\n        expiries[id] = block.timestamp + duration;\n        if(_exists(id)) {\n            // Name was previously owned, and expired\n            _burn(id);\n        }\n        _mint(owner, id);\n        if(updateRegistry) {\n            ens.setSubnodeOwner(baseNode, bytes32(id), owner);\n        }\n\n        emit NameRegistered(id, owner, block.timestamp + duration);\n\n        return block.timestamp + duration;\n    }\n\n    function renew(uint256 id, uint duration) external override live onlyController returns(uint) {\n        require(expiries[id] + GRACE_PERIOD >= block.timestamp); // Name must be registered here or in grace period\n        require(expiries[id] + duration + GRACE_PERIOD > duration + GRACE_PERIOD); // Prevent future overflow\n\n        expiries[id] += duration;\n        emit NameRenewed(id, expiries[id]);\n        return expiries[id];\n    }\n\n    /**\n     * @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\n     */\n    function reclaim(uint256 id, address owner) external override live {\n        require(_isApprovedOrOwner(msg.sender, id));\n        ens.setSubnodeOwner(baseNode, bytes32(id), owner);\n    }\n\n    function supportsInterface(bytes4 interfaceID) public override(ERC721, IERC165) view returns (bool) {\n        return interfaceID == INTERFACE_META_ID ||\n               interfaceID == ERC721_ID ||\n               interfaceID == RECLAIM_ID;\n    }\n}\n"
    },
    "contracts/resolvers/Resolver.sol": {
      "content": "pragma solidity >=0.8.4;\npragma experimental ABIEncoderV2;\n\n/**\n * A generic resolver interface which includes all the functions including the ones deprecated\n */\ninterface Resolver{\n    event AddrChanged(bytes32 indexed node, address a);\n    event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress);\n    event NameChanged(bytes32 indexed node, string name);\n    event ABIChanged(bytes32 indexed node, uint256 indexed contentType);\n    event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);\n    event TextChanged(bytes32 indexed node, string indexed indexedKey, string key);\n    event ContenthashChanged(bytes32 indexed node, bytes hash);\n    /* Deprecated events */\n    event ContentChanged(bytes32 indexed node, bytes32 hash);\n\n    function ABI(bytes32 node, uint256 contentTypes) external view returns (uint256, bytes memory);\n    function addr(bytes32 node) external view returns (address);\n    function addr(bytes32 node, uint coinType) external view returns(bytes memory);\n    function contenthash(bytes32 node) external view returns (bytes memory);\n    function dnsrr(bytes32 node) external view returns (bytes memory);\n    function name(bytes32 node) external view returns (string memory);\n    function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);\n    function text(bytes32 node, string calldata key) external view returns (string memory);\n    function interfaceImplementer(bytes32 node, bytes4 interfaceID) external view returns (address);\n    function setABI(bytes32 node, uint256 contentType, bytes calldata data) external;\n    function setAddr(bytes32 node, address addr) external;\n    function setAddr(bytes32 node, uint coinType, bytes calldata a) external;\n    function setContenthash(bytes32 node, bytes calldata hash) external;\n    function setDnsrr(bytes32 node, bytes calldata data) external;\n    function setName(bytes32 node, string calldata _name) external;\n    function setPubkey(bytes32 node, bytes32 x, bytes32 y) external;\n    function setText(bytes32 node, string calldata key, string calldata value) external;\n    function setInterface(bytes32 node, bytes4 interfaceID, address implementer) external;\n    function supportsInterface(bytes4 interfaceID) external pure returns (bool);\n    function multicall(bytes[] calldata data) external returns(bytes[] memory results);\n\n    /* Deprecated functions */\n    function content(bytes32 node) external view returns (bytes32);\n    function multihash(bytes32 node) external view returns (bytes memory);\n    function setContent(bytes32 node, bytes32 hash) external;\n    function setMultihash(bytes32 node, bytes calldata hash) external;\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/ERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n    using Address for address;\n    using Strings for uint256;\n\n    // Token name\n    string private _name;\n\n    // Token symbol\n    string private _symbol;\n\n    // Mapping from token ID to owner address\n    mapping (uint256 => address) private _owners;\n\n    // Mapping owner address to token count\n    mapping (address => uint256) private _balances;\n\n    // Mapping from token ID to approved address\n    mapping (uint256 => address) private _tokenApprovals;\n\n    // Mapping from owner to operator approvals\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\n\n    /**\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n     */\n    constructor (string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n        return interfaceId == type(IERC721).interfaceId\n            || interfaceId == type(IERC721Metadata).interfaceId\n            || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721-balanceOf}.\n     */\n    function balanceOf(address owner) public view virtual override returns (uint256) {\n        require(owner != address(0), \"ERC721: balance query for the zero address\");\n        return _balances[owner];\n    }\n\n    /**\n     * @dev See {IERC721-ownerOf}.\n     */\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n        address owner = _owners[tokenId];\n        require(owner != address(0), \"ERC721: owner query for nonexistent token\");\n        return owner;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-name}.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-symbol}.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-tokenURI}.\n     */\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n        require(_exists(tokenId), \"ERC721Metadata: URI query for nonexistent token\");\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length > 0\n            ? string(abi.encodePacked(baseURI, tokenId.toString()))\n            : '';\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. Empty by default, can be overriden\n     * in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return \"\";\n    }\n\n    /**\n     * @dev See {IERC721-approve}.\n     */\n    function approve(address to, uint256 tokenId) public virtual override {\n        address owner = ERC721.ownerOf(tokenId);\n        require(to != owner, \"ERC721: approval to current owner\");\n\n        require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n            \"ERC721: approve caller is not owner nor approved for all\"\n        );\n\n        _approve(to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-getApproved}.\n     */\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\n        require(_exists(tokenId), \"ERC721: approved query for nonexistent token\");\n\n        return _tokenApprovals[tokenId];\n    }\n\n    /**\n     * @dev See {IERC721-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual override {\n        require(operator != _msgSender(), \"ERC721: approve to caller\");\n\n        _operatorApprovals[_msgSender()][operator] = approved;\n        emit ApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /**\n     * @dev See {IERC721-isApprovedForAll}.\n     */\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    /**\n     * @dev See {IERC721-transferFrom}.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\n        //solhint-disable-next-line max-line-length\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n\n        _transfer(from, to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n        _safeTransfer(from, to, tokenId, _data);\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n     *\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\n        _transfer(from, to, tokenId);\n        require(_checkOnERC721Received(from, to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n    }\n\n    /**\n     * @dev Returns whether `tokenId` exists.\n     *\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n     *\n     * Tokens start existing when they are minted (`_mint`),\n     * and stop existing when they are burned (`_burn`).\n     */\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\n        return _owners[tokenId] != address(0);\n    }\n\n    /**\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n        require(_exists(tokenId), \"ERC721: operator query for nonexistent token\");\n        address owner = ERC721.ownerOf(tokenId);\n        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));\n    }\n\n    /**\n     * @dev Safely mints `tokenId` and transfers it to `to`.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeMint(address to, uint256 tokenId) internal virtual {\n        _safeMint(to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\n        _mint(to, tokenId);\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n    }\n\n    /**\n     * @dev Mints `tokenId` and transfers it to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - `to` cannot be the zero address.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _mint(address to, uint256 tokenId) internal virtual {\n        require(to != address(0), \"ERC721: mint to the zero address\");\n        require(!_exists(tokenId), \"ERC721: token already minted\");\n\n        _beforeTokenTransfer(address(0), to, tokenId);\n\n        _balances[to] += 1;\n        _owners[tokenId] = to;\n\n        emit Transfer(address(0), to, tokenId);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId) internal virtual {\n        address owner = ERC721.ownerOf(tokenId);\n\n        _beforeTokenTransfer(owner, address(0), tokenId);\n\n        // Clear approvals\n        _approve(address(0), tokenId);\n\n        _balances[owner] -= 1;\n        delete _owners[tokenId];\n\n        emit Transfer(owner, address(0), tokenId);\n    }\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\n        require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer of token that is not own\");\n        require(to != address(0), \"ERC721: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, tokenId);\n\n        // Clear approvals from the previous owner\n        _approve(address(0), tokenId);\n\n        _balances[from] -= 1;\n        _balances[to] += 1;\n        _owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n    }\n\n    /**\n     * @dev Approve `to` to operate on `tokenId`\n     *\n     * Emits a {Approval} event.\n     */\n    function _approve(address to, uint256 tokenId) internal virtual {\n        _tokenApprovals[tokenId] = to;\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n    }\n\n    /**\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n     * The call is not executed if the target address is not a contract.\n     *\n     * @param from address representing the previous owner of the given token ID\n     * @param to target address that will receive the tokens\n     * @param tokenId uint256 ID of the token to be transferred\n     * @param _data bytes optional data to send along with the call\n     * @return bool whether the call correctly returned the expected magic value\n     */\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\n        private returns (bool)\n    {\n        if (to.isContract()) {\n            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n                return retval == IERC721Receiver(to).onERC721Received.selector;\n            } catch (bytes memory reason) {\n                if (reason.length == 0) {\n                    revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n                } else {\n                    // solhint-disable-next-line no-inline-assembly\n                    assembly {\n                        revert(add(32, reason), mload(reason))\n                    }\n                }\n            }\n        } else {\n            return true;\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any token transfer. This includes minting\n     * and burning.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n     * transferred to `to`.\n     * - When `from` is zero, `tokenId` will be minted for `to`.\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\n}\n"
    },
    "contracts/ethregistrar/BaseRegistrar.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"../registry/ENS.sol\";\nimport \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nabstract contract BaseRegistrar is Ownable, IERC721 {\n    uint constant public GRACE_PERIOD = 90 days;\n\n    event ControllerAdded(address indexed controller);\n    event ControllerRemoved(address indexed controller);\n    event NameMigrated(uint256 indexed id, address indexed owner, uint expires);\n    event NameRegistered(uint256 indexed id, address indexed owner, uint expires);\n    event NameRenewed(uint256 indexed id, uint expires);\n\n    // The ENS registry\n    ENS public ens;\n\n    // The namehash of the TLD this registrar owns (eg, .eth)\n    bytes32 public baseNode;\n\n    // A map of addresses that are authorised to register and renew names.\n    mapping(address=>bool) public controllers;\n\n    // Authorises a controller, who can register and renew domains.\n    function addController(address controller) virtual external;\n\n    // Revoke controller permission for an address.\n    function removeController(address controller) virtual external;\n\n    // Set the resolver for the TLD this registrar manages.\n    function setResolver(address resolver) virtual external;\n\n    // Returns the expiration timestamp of the specified label hash.\n    function nameExpires(uint256 id) virtual external view returns(uint);\n\n    // Returns true iff the specified name is available for registration.\n    function available(uint256 id) virtual public view returns(bool);\n\n    /**\n     * @dev Register a name.\n     */\n    function register(uint256 id, address owner, uint duration) virtual external returns(uint);\n\n    function renew(uint256 id, uint duration) virtual external returns(uint);\n\n    /**\n     * @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\n     */\n    function reclaim(uint256 id, address owner) virtual external;\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/IERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool _approved) external;\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n\n    /**\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\n      *\n      * Requirements:\n      *\n      * - `from` cannot be the zero address.\n      * - `to` cannot be the zero address.\n      * - `tokenId` token must exist and be owned by `from`.\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n      *\n      * Emits a {Transfer} event.\n      */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\n     */\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
    },
    "@openzeppelin/contracts/utils/Address.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        // solhint-disable-next-line no-inline-assembly\n        assembly { size := extcodesize(account) }\n        return size > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n        (bool success, ) = recipient.call{ value: amount }(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain`call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n      return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\n        return _verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return _verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return _verifyCallResult(success, returndata, errorMessage);\n    }\n\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                // solhint-disable-next-line no-inline-assembly\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/Strings.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant alphabet = \"0123456789abcdef\";\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        // Inspired by OraclizeAPI's implementation - MIT licence\n        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n        if (value == 0) {\n            return \"0\";\n        }\n        uint256 temp = value;\n        uint256 digits;\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n        bytes memory buffer = new bytes(digits);\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return \"0x00\";\n        }\n        uint256 temp = value;\n        uint256 length = 0;\n        while (temp != 0) {\n            length++;\n            temp >>= 8;\n        }\n        return toHexString(value, length);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = alphabet[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/ERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
    },
    "contracts/ethregistrar/BulkRenewal.sol": {
      "content": "pragma solidity >=0.8.4;\npragma experimental ABIEncoderV2;\n\nimport \"../registry/ENS.sol\";\nimport \"./ETHRegistrarController.sol\";\nimport \"../resolvers/Resolver.sol\";\n\ncontract BulkRenewal {\n    bytes32 constant private ETH_NAMEHASH = 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\n    bytes4 constant private REGISTRAR_CONTROLLER_ID = 0x018fac06;\n    bytes4 constant private INTERFACE_META_ID = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n    bytes4 constant public BULK_RENEWAL_ID = bytes4(\n        keccak256(\"rentPrice(string[],uint)\") ^\n        keccak256(\"renewAll(string[],uint\")\n    );\n\n    ENS public ens;\n\n    constructor(ENS _ens) public {\n        ens = _ens;\n    }\n\n    function getController() internal view returns(ETHRegistrarController) {\n        Resolver r = Resolver(ens.resolver(ETH_NAMEHASH));\n        return ETHRegistrarController(r.interfaceImplementer(ETH_NAMEHASH, REGISTRAR_CONTROLLER_ID));\n    }\n\n    function rentPrice(string[] calldata names, uint duration) external view returns(uint total) {\n        ETHRegistrarController controller = getController();\n        for(uint i = 0; i < names.length; i++) {\n            total += controller.rentPrice(names[i], duration);\n        }\n    }\n\n    function renewAll(string[] calldata names, uint duration) external payable {\n        ETHRegistrarController controller = getController();\n        for(uint i = 0; i < names.length; i++) {\n            uint cost = controller.rentPrice(names[i], duration);\n            controller.renew{value:cost}(names[i], duration);\n        }\n        // Send any excess funds back\n        payable(msg.sender).transfer(address(this).balance);\n    }\n\n    function supportsInterface(bytes4 interfaceID) external pure returns (bool) {\n         return interfaceID == INTERFACE_META_ID || interfaceID == BULK_RENEWAL_ID;\n    }\n}\n"
    },
    "contracts/ethregistrar/LinearPremiumPriceOracle.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"./SafeMath.sol\";\nimport \"./StablePriceOracle.sol\";\n\ncontract LinearPremiumPriceOracle is StablePriceOracle {\n    using SafeMath for *;\n\n    uint GRACE_PERIOD = 90 days;\n\n    uint public initialPremium;\n    uint public premiumDecreaseRate;\n\n    bytes4 constant private TIME_UNTIL_PREMIUM_ID = bytes4(keccak256(\"timeUntilPremium(uint,uint\"));\n\n    constructor(AggregatorInterface _usdOracle, uint[] memory _rentPrices, uint _initialPremium, uint _premiumDecreaseRate) public\n        StablePriceOracle(_usdOracle, _rentPrices)\n    {\n        initialPremium = _initialPremium;\n        premiumDecreaseRate = _premiumDecreaseRate;\n    }\n\n    function _premium(string memory name, uint expires, uint /*duration*/) override internal view returns(uint) {\n        expires = expires.add(GRACE_PERIOD);\n        if(expires > block.timestamp) {\n            // No premium for renewals\n            return 0;\n        }\n\n        // Calculate the discount off the maximum premium\n        uint discount = premiumDecreaseRate.mul(block.timestamp.sub(expires));\n\n        // If we've run out the premium period, return 0.\n        if(discount > initialPremium) {\n            return 0;\n        }\n        \n        return initialPremium - discount;\n    }\n\n    /**\n     * @dev Returns the timestamp at which a name with the specified expiry date will have\n     *      the specified re-registration price premium.\n     * @param expires The timestamp at which the name expires.\n     * @param amount The amount, in wei, the caller is willing to pay\n     * @return The timestamp at which the premium for this domain will be `amount`.\n     */\n    function timeUntilPremium(uint expires, uint amount) external view returns(uint) {\n        amount = weiToAttoUSD(amount);\n        require(amount <= initialPremium);\n\n        expires = expires.add(GRACE_PERIOD);\n\n        uint discount = initialPremium.sub(amount);\n        uint duration = discount.div(premiumDecreaseRate);\n        return expires.add(duration);\n    }\n\n    function supportsInterface(bytes4 interfaceID) public view virtual override returns (bool) {\n        return (interfaceID == TIME_UNTIL_PREMIUM_ID) || super.supportsInterface(interfaceID);\n    }\n}\n"
    },
    "contracts/registry/TestRegistrar.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"./ENS.sol\";\n\n/**\n * A registrar that allocates subdomains to the first person to claim them, but\n * expires registrations a fixed period after they're initially claimed.\n */\ncontract TestRegistrar {\n    uint constant registrationPeriod = 4 weeks;\n\n    ENS public ens;\n    bytes32 public rootNode;\n    mapping (bytes32 => uint) public expiryTimes;\n\n    /**\n     * Constructor.\n     * @param ensAddr The address of the ENS registry.\n     * @param node The node that this registrar administers.\n     */\n    constructor(ENS ensAddr, bytes32 node) public {\n        ens = ensAddr;\n        rootNode = node;\n    }\n\n    /**\n     * Register a name that's not currently registered\n     * @param label The hash of the label to register.\n     * @param owner The address of the new owner.\n     */\n    function register(bytes32 label, address owner) public {\n        require(expiryTimes[label] < block.timestamp);\n\n        expiryTimes[label] = block.timestamp + registrationPeriod;\n        ens.setSubnodeOwner(rootNode, label, owner);\n    }\n}\n"
    },
    "contracts/registry/FIFSRegistrar.sol": {
      "content": "pragma solidity >=0.8.4;\n\nimport \"./ENS.sol\";\n\n/**\n * A registrar that allocates subdomains to the first person to claim them.\n */\ncontract FIFSRegistrar {\n    ENS ens;\n    bytes32 rootNode;\n\n    modifier only_owner(bytes32 label) {\n        address currentOwner = ens.owner(keccak256(abi.encodePacked(rootNode, label)));\n        require(currentOwner == address(0x0) || currentOwner == msg.sender);\n        _;\n    }\n\n    /**\n     * Constructor.\n     * @param ensAddr The address of the ENS registry.\n     * @param node The node that this registrar administers.\n     */\n    constructor(ENS ensAddr, bytes32 node) public {\n        ens = ensAddr;\n        rootNode = node;\n    }\n\n    /**\n     * Register a name, or change the owner of an existing registration.\n     * @param label The hash of the label to register.\n     * @param owner The address of the new owner.\n     */\n    function register(bytes32 label, address owner) public only_owner(label) {\n        ens.setSubnodeOwner(rootNode, label, owner);\n    }\n}\n"
    },
    "contracts/dnsregistrar/TLDPublicSuffixList.sol": {
      "content": "pragma solidity ^0.8.4;\n\nimport \"../dnssec-oracle/BytesUtils.sol\";\nimport \"./PublicSuffixList.sol\";\n\n/**\n * @dev A public suffix list that treats all TLDs as public suffixes.\n */\ncontract TLDPublicSuffixList is PublicSuffixList {\n    using BytesUtils for bytes;\n\n    function isPublicSuffix(bytes calldata name) external override view returns(bool) {\n        uint labellen = name.readUint8(0);\n        return labellen > 0 && name.readUint8(labellen + 1) == 0;\n    }\n}\n"
    },
    "contracts/dnsregistrar/SimplePublicSuffixList.sol": {
      "content": "pragma solidity ^0.8.4;\npragma experimental ABIEncoderV2;\n\nimport \"../root/Ownable.sol\";\nimport \"./PublicSuffixList.sol\";\n\ncontract SimplePublicSuffixList is PublicSuffixList, Ownable {\n    mapping(bytes=>bool) suffixes;\n\n    function addPublicSuffixes(bytes[] memory names) public onlyOwner {\n        for(uint i = 0; i < names.length; i++) {\n            suffixes[names[i]] = true;\n        }\n    }\n\n    function isPublicSuffix(bytes calldata name) external override view returns(bool) {\n        return suffixes[name];\n    }\n}\n"
    },
    "contracts/root/Ownable.sol": {
      "content": "pragma solidity ^0.8.4;\n\ncontract Ownable {\n\n    address public owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    modifier onlyOwner {\n        require(isOwner(msg.sender));\n        _;\n    }\n\n    constructor() public {\n        owner = msg.sender;\n    }\n\n    function transferOwnership(address newOwner) public onlyOwner {\n        emit OwnershipTransferred(owner, newOwner);\n        owner = newOwner;\n    }\n\n    function isOwner(address addr) public view returns (bool) {\n        return owner == addr;\n    }\n}\n"
    },
    "contracts/dnsregistrar/mocks/DummyDnsRegistrarDNSSEC.sol": {
      "content": "pragma solidity ^0.8.4;\n\ncontract DummyDNSSEC {\n    uint16 expectedType;\n    bytes expectedName;\n    uint32 inception;\n    uint64 inserted;\n    bytes20 hash;\n\n    function setData(uint16 _expectedType, bytes memory _expectedName, uint32 _inception, uint64 _inserted, bytes memory _proof) public {\n        expectedType = _expectedType;\n        expectedName = _expectedName;\n        inception = _inception;\n        inserted = _inserted;\n        if(_proof.length != 0) {\n            hash = bytes20(keccak256(_proof));\n        }\n    }\n\n    function rrdata(uint16 dnstype, bytes memory name) public view returns (uint32, uint64, bytes20) {\n        require(dnstype == expectedType);\n        require(keccak256(name) == keccak256(expectedName));\n        return (inception, inserted, hash);\n    }\n}\n"
    },
    "contracts/ethregistrar/DummyOracle.sol": {
      "content": "pragma solidity >=0.8.4;\n\ncontract DummyOracle {\n    int value;\n\n    constructor(int _value) public {\n        set(_value);\n    }\n\n    function set(int _value) public {\n        value = _value;\n    }\n\n    function latestAnswer() public view returns(int256) {\n        return value;\n    }\n}\n"
    },
    "contracts/ethregistrar/mocks/DummyProxyRegistry.sol": {
      "content": "pragma solidity >=0.8.4;\n\ncontract DummyProxyRegistry {\n    address target;\n\n    constructor(address _target) public {\n        target = _target;\n    }\n\n    function proxies(address a) external view returns(address) {\n        return target;\n    }\n}\n"
    },
    "contracts/ethregistrar/TestResolver.sol": {
      "content": "pragma solidity >=0.8.4;\n\n/**\n * @dev A test resolver implementation\n */\ncontract TestResolver {\n    mapping (bytes32 => address) addresses;\n\n    constructor() public {\n    }\n\n    function supportsInterface(bytes4 interfaceID) public pure returns (bool) {\n        return interfaceID == 0x01ffc9a7 || interfaceID == 0x3b3b57de;\n    }\n\n    function addr(bytes32 node) public view returns (address) {\n        return addresses[node];\n    }\n\n    function setAddr(bytes32 node, address addr) public {\n        addresses[node] = addr;\n    }\n}\n"
    },
    "contracts/resolvers/mocks/DummyNameWrapper.sol": {
      "content": "pragma solidity ^0.8.4;\n\n/**\n* @dev Implements a dummy NameWrapper which returns the caller's address\n*/\ncontract DummyNameWrapper {\n    function ownerOf(uint256 /* id */) public view returns (address) {\n        return tx.origin;\n    }\n}\n"
    },
    "test/registry/mocks/DummyResolver.sol": {
      "content": "pragma solidity >=0.8.4;\n\ncontract DummyResolver {\n\n    mapping (bytes32 => string) public name;\n\n    function setName(bytes32 node, string memory _name) public {\n        name[node] = _name;\n    }\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}