{
  "language": "Solidity",
  "sources": {
    "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/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/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/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/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/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"
    },
    "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/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/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    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/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/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/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/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/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/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"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}