{
  "address": "0x0fc3152971714E5ed7723FAFa650F86A4BaF30C5",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "_anchors",
          "type": "bytes"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "inputs": [
        {
          "internalType": "uint16",
          "name": "class",
          "type": "uint16"
        }
      ],
      "name": "InvalidClass",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "name",
          "type": "bytes"
        },
        {
          "internalType": "uint256",
          "name": "labelsExpected",
          "type": "uint256"
        }
      ],
      "name": "InvalidLabelCount",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint16",
          "name": "proofType",
          "type": "uint16"
        }
      ],
      "name": "InvalidProofType",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "InvalidRRSet",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "rrsetName",
          "type": "bytes"
        },
        {
          "internalType": "bytes",
          "name": "signerName",
          "type": "bytes"
        }
      ],
      "name": "InvalidSignerName",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "signerName",
          "type": "bytes"
        }
      ],
      "name": "NoMatchingProof",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "signerName",
          "type": "bytes"
        },
        {
          "internalType": "bytes",
          "name": "proofName",
          "type": "bytes"
        }
      ],
      "name": "ProofNameMismatch",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint32",
          "name": "expiration",
          "type": "uint32"
        },
        {
          "internalType": "uint32",
          "name": "now",
          "type": "uint32"
        }
      ],
      "name": "SignatureExpired",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint32",
          "name": "inception",
          "type": "uint32"
        },
        {
          "internalType": "uint32",
          "name": "now",
          "type": "uint32"
        }
      ],
      "name": "SignatureNotValidYet",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint16",
          "name": "rrsetType",
          "type": "uint16"
        },
        {
          "internalType": "uint16",
          "name": "sigType",
          "type": "uint16"
        }
      ],
      "name": "SignatureTypeMismatch",
      "type": "error"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint8",
          "name": "id",
          "type": "uint8"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "addr",
          "type": "address"
        }
      ],
      "name": "AlgorithmUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint8",
          "name": "id",
          "type": "uint8"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "addr",
          "type": "address"
        }
      ],
      "name": "DigestUpdated",
      "type": "event"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "",
          "type": "uint8"
        }
      ],
      "name": "algorithms",
      "outputs": [
        {
          "internalType": "contract Algorithm",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "anchors",
      "outputs": [
        {
          "internalType": "bytes",
          "name": "",
          "type": "bytes"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "",
          "type": "uint8"
        }
      ],
      "name": "digests",
      "outputs": [
        {
          "internalType": "contract Digest",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "id",
          "type": "uint8"
        },
        {
          "internalType": "contract Algorithm",
          "name": "algo",
          "type": "address"
        }
      ],
      "name": "setAlgorithm",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "id",
          "type": "uint8"
        },
        {
          "internalType": "contract Digest",
          "name": "digest",
          "type": "address"
        }
      ],
      "name": "setDigest",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "setOwner",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "bytes",
              "name": "rrset",
              "type": "bytes"
            },
            {
              "internalType": "bytes",
              "name": "sig",
              "type": "bytes"
            }
          ],
          "internalType": "struct DNSSEC.RRSetWithSignature[]",
          "name": "input",
          "type": "tuple[]"
        },
        {
          "internalType": "uint256",
          "name": "now",
          "type": "uint256"
        }
      ],
      "name": "verifyRRSet",
      "outputs": [
        {
          "internalType": "bytes",
          "name": "rrs",
          "type": "bytes"
        },
        {
          "internalType": "uint32",
          "name": "inception",
          "type": "uint32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "bytes",
              "name": "rrset",
              "type": "bytes"
            },
            {
              "internalType": "bytes",
              "name": "sig",
              "type": "bytes"
            }
          ],
          "internalType": "struct DNSSEC.RRSetWithSignature[]",
          "name": "input",
          "type": "tuple[]"
        }
      ],
      "name": "verifyRRSet",
      "outputs": [
        {
          "internalType": "bytes",
          "name": "rrs",
          "type": "bytes"
        },
        {
          "internalType": "uint32",
          "name": "inception",
          "type": "uint32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ],
  "transactionHash": "0xdd7b4a053abdb2548cf1814c34bb7bb8bc4c04fd40fca8ddaa9a5fa49c3dec39",
  "receipt": {
    "to": null,
    "from": "0x0904Dac3347eA47d208F3Fd67402D039a3b99859",
    "contractAddress": "0x0fc3152971714E5ed7723FAFa650F86A4BaF30C5",
    "transactionIndex": 34,
    "gasUsed": "1810348",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0xbd9e84737ca6669373a58feee7d18fbd6d17510a2b0efe542f5cf635a063fb9d",
    "transactionHash": "0xdd7b4a053abdb2548cf1814c34bb7bb8bc4c04fd40fca8ddaa9a5fa49c3dec39",
    "logs": [],
    "blockNumber": 19020686,
    "cumulativeGasUsed": "6427787",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0x00002b000100000e1000244a5c080249aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb500002b000100000e1000244f660802e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d"
  ],
  "numDeployments": 2,
  "solcInputHash": "dd9e022689821cffaeb04b9ddbda87ae",
  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_anchors\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"class\",\"type\":\"uint16\"}],\"name\":\"InvalidClass\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"labelsExpected\",\"type\":\"uint256\"}],\"name\":\"InvalidLabelCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"proofType\",\"type\":\"uint16\"}],\"name\":\"InvalidProofType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRRSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"rrsetName\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signerName\",\"type\":\"bytes\"}],\"name\":\"InvalidSignerName\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signerName\",\"type\":\"bytes\"}],\"name\":\"NoMatchingProof\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signerName\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofName\",\"type\":\"bytes\"}],\"name\":\"ProofNameMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expiration\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"now\",\"type\":\"uint32\"}],\"name\":\"SignatureExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"inception\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"now\",\"type\":\"uint32\"}],\"name\":\"SignatureNotValidYet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"rrsetType\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"sigType\",\"type\":\"uint16\"}],\"name\":\"SignatureTypeMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"AlgorithmUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"DigestUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"algorithms\",\"outputs\":[{\"internalType\":\"contract Algorithm\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"anchors\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"digests\",\"outputs\":[{\"internalType\":\"contract Digest\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"internalType\":\"contract Algorithm\",\"name\":\"algo\",\"type\":\"address\"}],\"name\":\"setAlgorithm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"internalType\":\"contract Digest\",\"name\":\"digest\",\"type\":\"address\"}],\"name\":\"setDigest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature[]\",\"name\":\"input\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"now\",\"type\":\"uint256\"}],\"name\":\"verifyRRSet\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"rrs\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"inception\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature[]\",\"name\":\"input\",\"type\":\"tuple[]\"}],\"name\":\"verifyRRSet\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"rrs\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"inception\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Constructor.\",\"params\":{\"_anchors\":\"The binary format RR entries for the root DS records.\"}},\"setAlgorithm(uint8,address)\":{\"details\":\"Sets the contract address for a signature verification algorithm.      Callable only by the owner.\",\"params\":{\"algo\":\"The address of the algorithm contract.\",\"id\":\"The algorithm ID\"}},\"setDigest(uint8,address)\":{\"details\":\"Sets the contract address for a digest verification algorithm.      Callable only by the owner.\",\"params\":{\"digest\":\"The address of the digest contract.\",\"id\":\"The digest ID\"}},\"verifyRRSet((bytes,bytes)[])\":{\"details\":\"Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.      Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.\",\"params\":{\"input\":\"A list of signed RRSets.\"},\"returns\":{\"inception\":\"The inception time of the signed record set.\",\"rrs\":\"The RRData from the last RRSet in the chain.\"}},\"verifyRRSet((bytes,bytes)[],uint256)\":{\"details\":\"Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.      Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.\",\"params\":{\"input\":\"A list of signed RRSets.\",\"now\":\"The Unix timestamp to validate the records at.\"},\"returns\":{\"inception\":\"The inception time of the signed record set.\",\"rrs\":\"The RRData from the last RRSet in the chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/DNSSECImpl.sol\":\"DNSSECImpl\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"@ensdomains/buffer/contracts/Buffer.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-2-Clause\\npragma solidity ^0.8.4;\\n\\n/**\\n* @dev A library for working with mutable byte buffers in Solidity.\\n*\\n* Byte buffers are mutable and expandable, and provide a variety of primitives\\n* for appending to them. At any time you can fetch a bytes object containing the\\n* current contents of the buffer. The bytes object should not be stored between\\n* operations, as it may change due to resizing of the buffer.\\n*/\\nlibrary Buffer {\\n    /**\\n    * @dev Represents a mutable buffer. Buffers have a current value (buf) and\\n    *      a capacity. The capacity may be longer than the current value, in\\n    *      which case it can be extended without the need to allocate more memory.\\n    */\\n    struct buffer {\\n        bytes buf;\\n        uint capacity;\\n    }\\n\\n    /**\\n    * @dev Initializes a buffer with an initial capacity.\\n    * @param buf The buffer to initialize.\\n    * @param capacity The number of bytes of space to allocate the buffer.\\n    * @return The buffer, for chaining.\\n    */\\n    function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {\\n        if (capacity % 32 != 0) {\\n            capacity += 32 - (capacity % 32);\\n        }\\n        // Allocate space for the buffer data\\n        buf.capacity = capacity;\\n        assembly {\\n            let ptr := mload(0x40)\\n            mstore(buf, ptr)\\n            mstore(ptr, 0)\\n            let fpm := add(32, add(ptr, capacity))\\n            if lt(fpm, ptr) {\\n                revert(0, 0)\\n            }\\n            mstore(0x40, fpm)\\n        }\\n        return buf;\\n    }\\n\\n    /**\\n    * @dev Initializes a new buffer from an existing bytes object.\\n    *      Changes to the buffer may mutate the original value.\\n    * @param b The bytes object to initialize the buffer with.\\n    * @return A new buffer.\\n    */\\n    function fromBytes(bytes memory b) internal pure returns(buffer memory) {\\n        buffer memory buf;\\n        buf.buf = b;\\n        buf.capacity = b.length;\\n        return buf;\\n    }\\n\\n    function resize(buffer memory buf, uint capacity) private pure {\\n        bytes memory oldbuf = buf.buf;\\n        init(buf, capacity);\\n        append(buf, oldbuf);\\n    }\\n\\n    /**\\n    * @dev Sets buffer length to 0.\\n    * @param buf The buffer to truncate.\\n    * @return The original buffer, for chaining..\\n    */\\n    function truncate(buffer memory buf) internal pure returns (buffer memory) {\\n        assembly {\\n            let bufptr := mload(buf)\\n            mstore(bufptr, 0)\\n        }\\n        return buf;\\n    }\\n\\n    /**\\n    * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed\\n    *      the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @param len The number of bytes to copy.\\n    * @return The original buffer, for chaining.\\n    */\\n    function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) {\\n        require(len <= data.length);\\n\\n        uint off = buf.buf.length;\\n        uint newCapacity = off + len;\\n        if (newCapacity > buf.capacity) {\\n            resize(buf, newCapacity * 2);\\n        }\\n\\n        uint dest;\\n        uint src;\\n        assembly {\\n            // Memory address of the buffer data\\n            let bufptr := mload(buf)\\n            // Length of existing buffer data\\n            let buflen := mload(bufptr)\\n            // Start address = buffer address + offset + sizeof(buffer length)\\n            dest := add(add(bufptr, 32), off)\\n            // Update buffer length if we're extending it\\n            if gt(newCapacity, buflen) {\\n                mstore(bufptr, newCapacity)\\n            }\\n            src := add(data, 32)\\n        }\\n\\n        // Copy word-length chunks while possible\\n        for (; len >= 32; len -= 32) {\\n            assembly {\\n                mstore(dest, mload(src))\\n            }\\n            dest += 32;\\n            src += 32;\\n        }\\n\\n        // Copy remaining bytes\\n        unchecked {\\n            uint mask = (256 ** (32 - len)) - 1;\\n            assembly {\\n                let srcpart := and(mload(src), not(mask))\\n                let destpart := and(mload(dest), mask)\\n                mstore(dest, or(destpart, srcpart))\\n            }\\n        }\\n\\n        return buf;\\n    }\\n\\n    /**\\n    * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\\n    *      the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @return The original buffer, for chaining.\\n    */\\n    function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\\n        return append(buf, data, data.length);\\n    }\\n\\n    /**\\n    * @dev Appends a byte to the buffer. Resizes if doing so would exceed the\\n    *      capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @return The original buffer, for chaining.\\n    */\\n    function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {\\n        uint off = buf.buf.length;\\n        uint offPlusOne = off + 1;\\n        if (off >= buf.capacity) {\\n            resize(buf, offPlusOne * 2);\\n        }\\n\\n        assembly {\\n            // Memory address of the buffer data\\n            let bufptr := mload(buf)\\n            // Address = buffer address + sizeof(buffer length) + off\\n            let dest := add(add(bufptr, off), 32)\\n            mstore8(dest, data)\\n            // Update buffer length if we extended it\\n            if gt(offPlusOne, mload(bufptr)) {\\n                mstore(bufptr, offPlusOne)\\n            }\\n        }\\n\\n        return buf;\\n    }\\n\\n    /**\\n    * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would\\n    *      exceed the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @param len The number of bytes to write (left-aligned).\\n    * @return The original buffer, for chaining.\\n    */\\n    function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) {\\n        uint off = buf.buf.length;\\n        uint newCapacity = len + off;\\n        if (newCapacity > buf.capacity) {\\n            resize(buf, newCapacity * 2);\\n        }\\n\\n        unchecked {\\n            uint mask = (256 ** len) - 1;\\n            // Right-align data\\n            data = data >> (8 * (32 - len));\\n            assembly {\\n                // Memory address of the buffer data\\n                let bufptr := mload(buf)\\n                // Address = buffer address + sizeof(buffer length) + newCapacity\\n                let dest := add(bufptr, newCapacity)\\n                mstore(dest, or(and(mload(dest), not(mask)), data))\\n                // Update buffer length if we extended it\\n                if gt(newCapacity, mload(bufptr)) {\\n                    mstore(bufptr, newCapacity)\\n                }\\n            }\\n        }\\n        return buf;\\n    }\\n\\n    /**\\n    * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed\\n    *      the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @return The original buffer, for chhaining.\\n    */\\n    function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {\\n        return append(buf, bytes32(data), 20);\\n    }\\n\\n    /**\\n    * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed\\n    *      the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @return The original buffer, for chaining.\\n    */\\n    function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {\\n        return append(buf, data, 32);\\n    }\\n\\n    /**\\n     * @dev Appends a byte to the end of the buffer. Resizes if doing so would\\n     *      exceed the capacity of the buffer.\\n     * @param buf The buffer to append to.\\n     * @param data The data to append.\\n     * @param len The number of bytes to write (right-aligned).\\n     * @return The original buffer.\\n     */\\n    function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {\\n        uint off = buf.buf.length;\\n        uint newCapacity = len + off;\\n        if (newCapacity > buf.capacity) {\\n            resize(buf, newCapacity * 2);\\n        }\\n\\n        uint mask = (256 ** len) - 1;\\n        assembly {\\n            // Memory address of the buffer data\\n            let bufptr := mload(buf)\\n            // Address = buffer address + sizeof(buffer length) + newCapacity\\n            let dest := add(bufptr, newCapacity)\\n            mstore(dest, or(and(mload(dest), not(mask)), data))\\n            // Update buffer length if we extended it\\n            if gt(newCapacity, mload(bufptr)) {\\n                mstore(bufptr, newCapacity)\\n            }\\n        }\\n        return buf;\\n    }\\n}\\n\",\"keccak256\":\"0xd6dd3b0b327288f8e1b711a609f4040fea602e2ad4bba9febdf2f33b4e56eb0c\",\"license\":\"BSD-2-Clause\"},\"contracts/dnssec-oracle/BytesUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary BytesUtils {\\n    error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n    /*\\n     * @dev Returns the keccak-256 hash of a byte range.\\n     * @param self The byte string to hash.\\n     * @param offset The position to start hashing at.\\n     * @param len The number of bytes to hash.\\n     * @return The hash of the byte range.\\n     */\\n    function keccak(\\n        bytes memory self,\\n        uint256 offset,\\n        uint256 len\\n    ) internal pure returns (bytes32 ret) {\\n        require(offset + len <= self.length);\\n        assembly {\\n            ret := keccak256(add(add(self, 32), offset), len)\\n        }\\n    }\\n\\n    /*\\n     * @dev Returns a positive number if `other` comes lexicographically after\\n     *      `self`, a negative number if it comes before, or zero if the\\n     *      contents of the two bytes are equal.\\n     * @param self The first bytes to compare.\\n     * @param other The second bytes to compare.\\n     * @return The result of the comparison.\\n     */\\n    function compare(\\n        bytes memory self,\\n        bytes memory other\\n    ) internal pure returns (int256) {\\n        return compare(self, 0, self.length, other, 0, other.length);\\n    }\\n\\n    /*\\n     * @dev Returns a positive number if `other` comes lexicographically after\\n     *      `self`, a negative number if it comes before, or zero if the\\n     *      contents of the two bytes are equal. Comparison is done per-rune,\\n     *      on unicode codepoints.\\n     * @param self The first bytes to compare.\\n     * @param offset The offset of self.\\n     * @param len    The length of self.\\n     * @param other The second bytes to compare.\\n     * @param otheroffset The offset of the other string.\\n     * @param otherlen    The length of the other string.\\n     * @return The result of the comparison.\\n     */\\n    function compare(\\n        bytes memory self,\\n        uint256 offset,\\n        uint256 len,\\n        bytes memory other,\\n        uint256 otheroffset,\\n        uint256 otherlen\\n    ) internal pure returns (int256) {\\n        if (offset + len > self.length) {\\n            revert OffsetOutOfBoundsError(offset + len, self.length);\\n        }\\n        if (otheroffset + otherlen > other.length) {\\n            revert OffsetOutOfBoundsError(otheroffset + otherlen, other.length);\\n        }\\n\\n        uint256 shortest = len;\\n        if (otherlen < len) shortest = otherlen;\\n\\n        uint256 selfptr;\\n        uint256 otherptr;\\n\\n        assembly {\\n            selfptr := add(self, add(offset, 32))\\n            otherptr := add(other, add(otheroffset, 32))\\n        }\\n        for (uint256 idx = 0; idx < shortest; idx += 32) {\\n            uint256 a;\\n            uint256 b;\\n            assembly {\\n                a := mload(selfptr)\\n                b := mload(otherptr)\\n            }\\n            if (a != b) {\\n                // Mask out irrelevant bytes and check again\\n                uint256 mask;\\n                if (shortest - idx >= 32) {\\n                    mask = type(uint256).max;\\n                } else {\\n                    mask = ~(2 ** (8 * (idx + 32 - shortest)) - 1);\\n                }\\n                int256 diff = int256(a & mask) - int256(b & mask);\\n                if (diff != 0) return diff;\\n            }\\n            selfptr += 32;\\n            otherptr += 32;\\n        }\\n\\n        return int256(len) - int256(otherlen);\\n    }\\n\\n    /*\\n     * @dev Returns true if the two byte ranges are equal.\\n     * @param self The first byte range to compare.\\n     * @param offset The offset into the first byte range.\\n     * @param other The second byte range to compare.\\n     * @param otherOffset The offset into the second byte range.\\n     * @param len The number of bytes to compare\\n     * @return True if the byte ranges are equal, false otherwise.\\n     */\\n    function equals(\\n        bytes memory self,\\n        uint256 offset,\\n        bytes memory other,\\n        uint256 otherOffset,\\n        uint256 len\\n    ) internal pure returns (bool) {\\n        return keccak(self, offset, len) == keccak(other, otherOffset, len);\\n    }\\n\\n    /*\\n     * @dev Returns true if the two byte ranges are equal with offsets.\\n     * @param self The first byte range to compare.\\n     * @param offset The offset into the first byte range.\\n     * @param other The second byte range to compare.\\n     * @param otherOffset The offset into the second byte range.\\n     * @return True if the byte ranges are equal, false otherwise.\\n     */\\n    function equals(\\n        bytes memory self,\\n        uint256 offset,\\n        bytes memory other,\\n        uint256 otherOffset\\n    ) internal pure returns (bool) {\\n        return\\n            keccak(self, offset, self.length - offset) ==\\n            keccak(other, otherOffset, other.length - otherOffset);\\n    }\\n\\n    /*\\n     * @dev Compares a range of 'self' to all of 'other' and returns True iff\\n     *      they are equal.\\n     * @param self The first byte range to compare.\\n     * @param offset The offset into the first byte range.\\n     * @param other The second byte range to compare.\\n     * @return True if the byte ranges are equal, false otherwise.\\n     */\\n    function equals(\\n        bytes memory self,\\n        uint256 offset,\\n        bytes memory other\\n    ) internal pure returns (bool) {\\n        return\\n            self.length == offset + other.length &&\\n            equals(self, offset, other, 0, other.length);\\n    }\\n\\n    /*\\n     * @dev Returns true if the two byte ranges are equal.\\n     * @param self The first byte range to compare.\\n     * @param other The second byte range to compare.\\n     * @return True if the byte ranges are equal, false otherwise.\\n     */\\n    function equals(\\n        bytes memory self,\\n        bytes memory other\\n    ) internal pure returns (bool) {\\n        return\\n            self.length == other.length &&\\n            equals(self, 0, other, 0, self.length);\\n    }\\n\\n    /*\\n     * @dev Returns the 8-bit number at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes\\n     * @return The specified 8 bits of the string, interpreted as an integer.\\n     */\\n    function readUint8(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (uint8 ret) {\\n        return uint8(self[idx]);\\n    }\\n\\n    /*\\n     * @dev Returns the 16-bit number at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes\\n     * @return The specified 16 bits of the string, interpreted as an integer.\\n     */\\n    function readUint16(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (uint16 ret) {\\n        require(idx + 2 <= self.length);\\n        assembly {\\n            ret := and(mload(add(add(self, 2), idx)), 0xFFFF)\\n        }\\n    }\\n\\n    /*\\n     * @dev Returns the 32-bit number at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes\\n     * @return The specified 32 bits of the string, interpreted as an integer.\\n     */\\n    function readUint32(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (uint32 ret) {\\n        require(idx + 4 <= self.length);\\n        assembly {\\n            ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF)\\n        }\\n    }\\n\\n    /*\\n     * @dev Returns the 32 byte value at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes\\n     * @return The specified 32 bytes of the string.\\n     */\\n    function readBytes32(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (bytes32 ret) {\\n        require(idx + 32 <= self.length);\\n        assembly {\\n            ret := mload(add(add(self, 32), idx))\\n        }\\n    }\\n\\n    /*\\n     * @dev Returns the 32 byte value at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes\\n     * @return The specified 32 bytes of the string.\\n     */\\n    function readBytes20(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (bytes20 ret) {\\n        require(idx + 20 <= self.length);\\n        assembly {\\n            ret := and(\\n                mload(add(add(self, 32), idx)),\\n                0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000\\n            )\\n        }\\n    }\\n\\n    /*\\n     * @dev Returns the n byte value at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes.\\n     * @param len The number of bytes.\\n     * @return The specified 32 bytes of the string.\\n     */\\n    function readBytesN(\\n        bytes memory self,\\n        uint256 idx,\\n        uint256 len\\n    ) internal pure returns (bytes32 ret) {\\n        require(len <= 32);\\n        require(idx + len <= self.length);\\n        assembly {\\n            let mask := not(sub(exp(256, sub(32, len)), 1))\\n            ret := and(mload(add(add(self, 32), idx)), mask)\\n        }\\n    }\\n\\n    function memcpy(uint256 dest, uint256 src, uint256 len) private pure {\\n        // Copy word-length chunks while possible\\n        for (; len >= 32; len -= 32) {\\n            assembly {\\n                mstore(dest, mload(src))\\n            }\\n            dest += 32;\\n            src += 32;\\n        }\\n\\n        // Copy remaining bytes\\n        unchecked {\\n            uint256 mask = (256 ** (32 - len)) - 1;\\n            assembly {\\n                let srcpart := and(mload(src), not(mask))\\n                let destpart := and(mload(dest), mask)\\n                mstore(dest, or(destpart, srcpart))\\n            }\\n        }\\n    }\\n\\n    /*\\n     * @dev Copies a substring into a new byte string.\\n     * @param self The byte string to copy from.\\n     * @param offset The offset to start copying at.\\n     * @param len The number of bytes to copy.\\n     */\\n    function substring(\\n        bytes memory self,\\n        uint256 offset,\\n        uint256 len\\n    ) internal pure returns (bytes memory) {\\n        require(offset + len <= self.length);\\n\\n        bytes memory ret = new bytes(len);\\n        uint256 dest;\\n        uint256 src;\\n\\n        assembly {\\n            dest := add(ret, 32)\\n            src := add(add(self, 32), offset)\\n        }\\n        memcpy(dest, src, len);\\n\\n        return ret;\\n    }\\n\\n    // Maps characters from 0x30 to 0x7A to their base32 values.\\n    // 0xFF represents invalid characters in that range.\\n    bytes constant base32HexTable =\\n        hex\\\"00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\\\";\\n\\n    /**\\n     * @dev Decodes unpadded base32 data of up to one word in length.\\n     * @param self The data to decode.\\n     * @param off Offset into the string to start at.\\n     * @param len Number of characters to decode.\\n     * @return The decoded data, left aligned.\\n     */\\n    function base32HexDecodeWord(\\n        bytes memory self,\\n        uint256 off,\\n        uint256 len\\n    ) internal pure returns (bytes32) {\\n        require(len <= 52);\\n\\n        uint256 ret = 0;\\n        uint8 decoded;\\n        for (uint256 i = 0; i < len; i++) {\\n            bytes1 char = self[off + i];\\n            require(char >= 0x30 && char <= 0x7A);\\n            decoded = uint8(base32HexTable[uint256(uint8(char)) - 0x30]);\\n            require(decoded <= 0x20);\\n            if (i == len - 1) {\\n                break;\\n            }\\n            ret = (ret << 5) | decoded;\\n        }\\n\\n        uint256 bitlen = len * 5;\\n        if (len % 8 == 0) {\\n            // Multiple of 8 characters, no padding\\n            ret = (ret << 5) | decoded;\\n        } else if (len % 8 == 2) {\\n            // Two extra characters - 1 byte\\n            ret = (ret << 3) | (decoded >> 2);\\n            bitlen -= 2;\\n        } else if (len % 8 == 4) {\\n            // Four extra characters - 2 bytes\\n            ret = (ret << 1) | (decoded >> 4);\\n            bitlen -= 4;\\n        } else if (len % 8 == 5) {\\n            // Five extra characters - 3 bytes\\n            ret = (ret << 4) | (decoded >> 1);\\n            bitlen -= 1;\\n        } else if (len % 8 == 7) {\\n            // Seven extra characters - 4 bytes\\n            ret = (ret << 2) | (decoded >> 3);\\n            bitlen -= 3;\\n        } else {\\n            revert();\\n        }\\n\\n        return bytes32(ret << (256 - bitlen));\\n    }\\n\\n    /**\\n     * @dev Finds the first occurrence of the byte `needle` in `self`.\\n     * @param self The string to search\\n     * @param off The offset to start searching at\\n     * @param len The number of bytes to search\\n     * @param needle The byte to search for\\n     * @return The offset of `needle` in `self`, or 2**256-1 if it was not found.\\n     */\\n    function find(\\n        bytes memory self,\\n        uint256 off,\\n        uint256 len,\\n        bytes1 needle\\n    ) internal pure returns (uint256) {\\n        for (uint256 idx = off; idx < off + len; idx++) {\\n            if (self[idx] == needle) {\\n                return idx;\\n            }\\n        }\\n        return type(uint256).max;\\n    }\\n}\\n\",\"keccak256\":\"0x4f10902639b85a17ae10745264feff322e793bfb1bc130a9a90efa7dda47c6cc\"},\"contracts/dnssec-oracle/DNSSEC.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\npragma experimental ABIEncoderV2;\\n\\nabstract contract DNSSEC {\\n    bytes public anchors;\\n\\n    struct RRSetWithSignature {\\n        bytes rrset;\\n        bytes sig;\\n    }\\n\\n    event AlgorithmUpdated(uint8 id, address addr);\\n    event DigestUpdated(uint8 id, address addr);\\n\\n    function verifyRRSet(\\n        RRSetWithSignature[] memory input\\n    ) external view virtual returns (bytes memory rrs, uint32 inception);\\n\\n    function verifyRRSet(\\n        RRSetWithSignature[] memory input,\\n        uint256 now\\n    ) public view virtual returns (bytes memory rrs, uint32 inception);\\n}\\n\",\"keccak256\":\"0xee6a236a59e5db8418c98ee4640a91987d26533c02d305cc6c7a37a3ac4ee907\",\"license\":\"MIT\"},\"contracts/dnssec-oracle/DNSSECImpl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"./Owned.sol\\\";\\nimport \\\"./BytesUtils.sol\\\";\\nimport \\\"./RRUtils.sol\\\";\\nimport \\\"./DNSSEC.sol\\\";\\nimport \\\"./algorithms/Algorithm.sol\\\";\\nimport \\\"./digests/Digest.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\n/*\\n * @dev An oracle contract that verifies and stores DNSSEC-validated DNS records.\\n * @note This differs from the DNSSEC spec defined in RFC4034 and RFC4035 in some key regards:\\n *       - NSEC & NSEC3 are not supported; only positive proofs are allowed.\\n *       - Proofs involving wildcard names will not validate.\\n *       - TTLs on records are ignored, as data is not stored persistently.\\n *       - Canonical form of names is not checked; in ENS this is done on the frontend, so submitting\\n *         proofs with non-canonical names will only result in registering unresolvable ENS names.\\n */\\ncontract DNSSECImpl is DNSSEC, Owned {\\n    using Buffer for Buffer.buffer;\\n    using BytesUtils for bytes;\\n    using RRUtils for *;\\n\\n    uint16 constant DNSCLASS_IN = 1;\\n\\n    uint16 constant DNSTYPE_DS = 43;\\n    uint16 constant DNSTYPE_DNSKEY = 48;\\n\\n    uint256 constant DNSKEY_FLAG_ZONEKEY = 0x100;\\n\\n    error InvalidLabelCount(bytes name, uint256 labelsExpected);\\n    error SignatureNotValidYet(uint32 inception, uint32 now);\\n    error SignatureExpired(uint32 expiration, uint32 now);\\n    error InvalidClass(uint16 class);\\n    error InvalidRRSet();\\n    error SignatureTypeMismatch(uint16 rrsetType, uint16 sigType);\\n    error InvalidSignerName(bytes rrsetName, bytes signerName);\\n    error InvalidProofType(uint16 proofType);\\n    error ProofNameMismatch(bytes signerName, bytes proofName);\\n    error NoMatchingProof(bytes signerName);\\n\\n    mapping(uint8 => Algorithm) public algorithms;\\n    mapping(uint8 => Digest) public digests;\\n\\n    /**\\n     * @dev Constructor.\\n     * @param _anchors The binary format RR entries for the root DS records.\\n     */\\n    constructor(bytes memory _anchors) {\\n        // Insert the 'trust anchors' - the key hashes that start the chain\\n        // of trust for all other records.\\n        anchors = _anchors;\\n    }\\n\\n    /**\\n     * @dev Sets the contract address for a signature verification algorithm.\\n     *      Callable only by the owner.\\n     * @param id The algorithm ID\\n     * @param algo The address of the algorithm contract.\\n     */\\n    function setAlgorithm(uint8 id, Algorithm algo) public owner_only {\\n        algorithms[id] = algo;\\n        emit AlgorithmUpdated(id, address(algo));\\n    }\\n\\n    /**\\n     * @dev Sets the contract address for a digest verification algorithm.\\n     *      Callable only by the owner.\\n     * @param id The digest ID\\n     * @param digest The address of the digest contract.\\n     */\\n    function setDigest(uint8 id, Digest digest) public owner_only {\\n        digests[id] = digest;\\n        emit DigestUpdated(id, address(digest));\\n    }\\n\\n    /**\\n     * @dev Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.\\n     *      Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.\\n     * @param input A list of signed RRSets.\\n     * @return rrs The RRData from the last RRSet in the chain.\\n     * @return inception The inception time of the signed record set.\\n     */\\n    function verifyRRSet(\\n        RRSetWithSignature[] memory input\\n    )\\n        external\\n        view\\n        virtual\\n        override\\n        returns (bytes memory rrs, uint32 inception)\\n    {\\n        return verifyRRSet(input, block.timestamp);\\n    }\\n\\n    /**\\n     * @dev Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.\\n     *      Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.\\n     * @param input A list of signed RRSets.\\n     * @param now The Unix timestamp to validate the records at.\\n     * @return rrs The RRData from the last RRSet in the chain.\\n     * @return inception The inception time of the signed record set.\\n     */\\n    function verifyRRSet(\\n        RRSetWithSignature[] memory input,\\n        uint256 now\\n    )\\n        public\\n        view\\n        virtual\\n        override\\n        returns (bytes memory rrs, uint32 inception)\\n    {\\n        bytes memory proof = anchors;\\n        for (uint256 i = 0; i < input.length; i++) {\\n            RRUtils.SignedSet memory rrset = validateSignedSet(\\n                input[i],\\n                proof,\\n                now\\n            );\\n            proof = rrset.data;\\n            inception = rrset.inception;\\n        }\\n        return (proof, inception);\\n    }\\n\\n    /**\\n     * @dev Validates an RRSet against the already trusted RR provided in `proof`.\\n     *\\n     * @param input The signed RR set. This is in the format described in section\\n     *        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature\\n     *        data, followed by a series of canonicalised RR records that the signature\\n     *        applies to.\\n     * @param proof The DNSKEY or DS to validate the signature against.\\n     * @param now The current timestamp.\\n     */\\n    function validateSignedSet(\\n        RRSetWithSignature memory input,\\n        bytes memory proof,\\n        uint256 now\\n    ) internal view returns (RRUtils.SignedSet memory rrset) {\\n        rrset = input.rrset.readSignedSet();\\n\\n        // Do some basic checks on the RRs and extract the name\\n        bytes memory name = validateRRs(rrset, rrset.typeCovered);\\n        if (name.labelCount(0) != rrset.labels) {\\n            revert InvalidLabelCount(name, rrset.labels);\\n        }\\n        rrset.name = name;\\n\\n        // All comparisons involving the Signature Expiration and\\n        // Inception fields MUST use \\\"serial number arithmetic\\\", as\\n        // defined in RFC 1982\\n\\n        // o  The validator's notion of the current time MUST be less than or\\n        //    equal to the time listed in the RRSIG RR's Expiration field.\\n        if (!RRUtils.serialNumberGte(rrset.expiration, uint32(now))) {\\n            revert SignatureExpired(rrset.expiration, uint32(now));\\n        }\\n\\n        // o  The validator's notion of the current time MUST be greater than or\\n        //    equal to the time listed in the RRSIG RR's Inception field.\\n        if (!RRUtils.serialNumberGte(uint32(now), rrset.inception)) {\\n            revert SignatureNotValidYet(rrset.inception, uint32(now));\\n        }\\n\\n        // Validate the signature\\n        verifySignature(name, rrset, input, proof);\\n\\n        return rrset;\\n    }\\n\\n    /**\\n     * @dev Validates a set of RRs.\\n     * @param rrset The RR set.\\n     * @param typecovered The type covered by the RRSIG record.\\n     */\\n    function validateRRs(\\n        RRUtils.SignedSet memory rrset,\\n        uint16 typecovered\\n    ) internal pure returns (bytes memory name) {\\n        // Iterate over all the RRs\\n        for (\\n            RRUtils.RRIterator memory iter = rrset.rrs();\\n            !iter.done();\\n            iter.next()\\n        ) {\\n            // We only support class IN (Internet)\\n            if (iter.class != DNSCLASS_IN) {\\n                revert InvalidClass(iter.class);\\n            }\\n\\n            if (name.length == 0) {\\n                name = iter.name();\\n            } else {\\n                // Name must be the same on all RRs. We do things this way to avoid copying the name\\n                // repeatedly.\\n                if (\\n                    name.length != iter.data.nameLength(iter.offset) ||\\n                    !name.equals(0, iter.data, iter.offset, name.length)\\n                ) {\\n                    revert InvalidRRSet();\\n                }\\n            }\\n\\n            // o  The RRSIG RR's Type Covered field MUST equal the RRset's type.\\n            if (iter.dnstype != typecovered) {\\n                revert SignatureTypeMismatch(iter.dnstype, typecovered);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @dev Performs signature verification.\\n     *\\n     * Throws or reverts if unable to verify the record.\\n     *\\n     * @param name The name of the RRSIG record, in DNS label-sequence format.\\n     * @param data The original data to verify.\\n     * @param proof A DS or DNSKEY record that's already verified by the oracle.\\n     */\\n    function verifySignature(\\n        bytes memory name,\\n        RRUtils.SignedSet memory rrset,\\n        RRSetWithSignature memory data,\\n        bytes memory proof\\n    ) internal view {\\n        // o  The RRSIG RR's Signer's Name field MUST be the name of the zone\\n        //    that contains the RRset.\\n        if (!name.isSubdomainOf(rrset.signerName)) {\\n            revert InvalidSignerName(name, rrset.signerName);\\n        }\\n\\n        RRUtils.RRIterator memory proofRR = proof.iterateRRs(0);\\n        // Check the proof\\n        if (proofRR.dnstype == DNSTYPE_DS) {\\n            verifyWithDS(rrset, data, proofRR);\\n        } else if (proofRR.dnstype == DNSTYPE_DNSKEY) {\\n            verifyWithKnownKey(rrset, data, proofRR);\\n        } else {\\n            revert InvalidProofType(proofRR.dnstype);\\n        }\\n    }\\n\\n    /**\\n     * @dev Attempts to verify a signed RRSET against an already known public key.\\n     * @param rrset The signed set to verify.\\n     * @param data The original data the signed set was read from.\\n     * @param proof The serialized DS or DNSKEY record to use as proof.\\n     */\\n    function verifyWithKnownKey(\\n        RRUtils.SignedSet memory rrset,\\n        RRSetWithSignature memory data,\\n        RRUtils.RRIterator memory proof\\n    ) internal view {\\n        // Check the DNSKEY's owner name matches the signer name on the RRSIG\\n        for (; !proof.done(); proof.next()) {\\n            bytes memory proofName = proof.name();\\n            if (!proofName.equals(rrset.signerName)) {\\n                revert ProofNameMismatch(rrset.signerName, proofName);\\n            }\\n\\n            bytes memory keyrdata = proof.rdata();\\n            RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(\\n                0,\\n                keyrdata.length\\n            );\\n            if (verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {\\n                return;\\n            }\\n        }\\n        revert NoMatchingProof(rrset.signerName);\\n    }\\n\\n    /**\\n     * @dev Attempts to verify some data using a provided key and a signature.\\n     * @param dnskey The dns key record to verify the signature with.\\n     * @param rrset The signed RRSET being verified.\\n     * @param data The original data `rrset` was decoded from.\\n     * @return True iff the key verifies the signature.\\n     */\\n    function verifySignatureWithKey(\\n        RRUtils.DNSKEY memory dnskey,\\n        bytes memory keyrdata,\\n        RRUtils.SignedSet memory rrset,\\n        RRSetWithSignature memory data\\n    ) internal view returns (bool) {\\n        // TODO: Check key isn't expired, unless updating key itself\\n\\n        // The Protocol Field MUST have value 3 (RFC4034 2.1.2)\\n        if (dnskey.protocol != 3) {\\n            return false;\\n        }\\n\\n        // o The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST\\n        //   match the owner name, algorithm, and key tag for some DNSKEY RR in\\n        //   the zone's apex DNSKEY RRset.\\n        if (dnskey.algorithm != rrset.algorithm) {\\n            return false;\\n        }\\n        uint16 computedkeytag = keyrdata.computeKeytag();\\n        if (computedkeytag != rrset.keytag) {\\n            return false;\\n        }\\n\\n        // o The matching DNSKEY RR MUST be present in the zone's apex DNSKEY\\n        //   RRset, and MUST have the Zone Flag bit (DNSKEY RDATA Flag bit 7)\\n        //   set.\\n        if (dnskey.flags & DNSKEY_FLAG_ZONEKEY == 0) {\\n            return false;\\n        }\\n\\n        Algorithm algorithm = algorithms[dnskey.algorithm];\\n        if (address(algorithm) == address(0)) {\\n            return false;\\n        }\\n        return algorithm.verify(keyrdata, data.rrset, data.sig);\\n    }\\n\\n    /**\\n     * @dev Attempts to verify a signed RRSET against an already known hash. This function assumes\\n     *      that the record\\n     * @param rrset The signed set to verify.\\n     * @param data The original data the signed set was read from.\\n     * @param proof The serialized DS or DNSKEY record to use as proof.\\n     */\\n    function verifyWithDS(\\n        RRUtils.SignedSet memory rrset,\\n        RRSetWithSignature memory data,\\n        RRUtils.RRIterator memory proof\\n    ) internal view {\\n        uint256 proofOffset = proof.offset;\\n        for (\\n            RRUtils.RRIterator memory iter = rrset.rrs();\\n            !iter.done();\\n            iter.next()\\n        ) {\\n            if (iter.dnstype != DNSTYPE_DNSKEY) {\\n                revert InvalidProofType(iter.dnstype);\\n            }\\n\\n            bytes memory keyrdata = iter.rdata();\\n            RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(\\n                0,\\n                keyrdata.length\\n            );\\n            if (verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {\\n                // It's self-signed - look for a DS record to verify it.\\n                if (\\n                    verifyKeyWithDS(rrset.signerName, proof, dnskey, keyrdata)\\n                ) {\\n                    return;\\n                }\\n                // Rewind proof iterator to the start for the next loop iteration.\\n                proof.nextOffset = proofOffset;\\n                proof.next();\\n            }\\n        }\\n        revert NoMatchingProof(rrset.signerName);\\n    }\\n\\n    /**\\n     * @dev Attempts to verify a key using DS records.\\n     * @param keyname The DNS name of the key, in DNS label-sequence format.\\n     * @param dsrrs The DS records to use in verification.\\n     * @param dnskey The dnskey to verify.\\n     * @param keyrdata The RDATA section of the key.\\n     * @return True if a DS record verifies this key.\\n     */\\n    function verifyKeyWithDS(\\n        bytes memory keyname,\\n        RRUtils.RRIterator memory dsrrs,\\n        RRUtils.DNSKEY memory dnskey,\\n        bytes memory keyrdata\\n    ) internal view returns (bool) {\\n        uint16 keytag = keyrdata.computeKeytag();\\n        for (; !dsrrs.done(); dsrrs.next()) {\\n            bytes memory proofName = dsrrs.name();\\n            if (!proofName.equals(keyname)) {\\n                revert ProofNameMismatch(keyname, proofName);\\n            }\\n\\n            RRUtils.DS memory ds = dsrrs.data.readDS(\\n                dsrrs.rdataOffset,\\n                dsrrs.nextOffset - dsrrs.rdataOffset\\n            );\\n            if (ds.keytag != keytag) {\\n                continue;\\n            }\\n            if (ds.algorithm != dnskey.algorithm) {\\n                continue;\\n            }\\n\\n            Buffer.buffer memory buf;\\n            buf.init(keyname.length + keyrdata.length);\\n            buf.append(keyname);\\n            buf.append(keyrdata);\\n            if (verifyDSHash(ds.digestType, buf.buf, ds.digest)) {\\n                return true;\\n            }\\n        }\\n        return false;\\n    }\\n\\n    /**\\n     * @dev Attempts to verify a DS record's hash value against some data.\\n     * @param digesttype The digest ID from the DS record.\\n     * @param data The data to digest.\\n     * @param digest The digest data to check against.\\n     * @return True iff the digest matches.\\n     */\\n    function verifyDSHash(\\n        uint8 digesttype,\\n        bytes memory data,\\n        bytes memory digest\\n    ) internal view returns (bool) {\\n        if (address(digests[digesttype]) == address(0)) {\\n            return false;\\n        }\\n        return digests[digesttype].verify(data, digest);\\n    }\\n}\\n\",\"keccak256\":\"0x671fea3a3332453eecc08c082f264011aa8cfa99fb3c03adf73443843aed5128\",\"license\":\"MIT\"},\"contracts/dnssec-oracle/Owned.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @dev Contract mixin for 'owned' contracts.\\n */\\ncontract Owned {\\n    address public owner;\\n\\n    modifier owner_only() {\\n        require(msg.sender == owner);\\n        _;\\n    }\\n\\n    constructor() public {\\n        owner = msg.sender;\\n    }\\n\\n    function setOwner(address newOwner) public owner_only {\\n        owner = newOwner;\\n    }\\n}\\n\",\"keccak256\":\"0x49f57dcb9d79015f917e569b4318b766bee9920f72e11a1f5331eabebfc1eb24\"},\"contracts/dnssec-oracle/RRUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./BytesUtils.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\n/**\\n * @dev RRUtils is a library that provides utilities for parsing DNS resource records.\\n */\\nlibrary RRUtils {\\n    using BytesUtils for *;\\n    using Buffer for *;\\n\\n    /**\\n     * @dev Returns the number of bytes in the DNS name at 'offset' in 'self'.\\n     * @param self The byte array to read a name from.\\n     * @param offset The offset to start reading at.\\n     * @return The length of the DNS name at 'offset', in bytes.\\n     */\\n    function nameLength(\\n        bytes memory self,\\n        uint256 offset\\n    ) internal pure returns (uint256) {\\n        uint256 idx = offset;\\n        while (true) {\\n            assert(idx < self.length);\\n            uint256 labelLen = self.readUint8(idx);\\n            idx += labelLen + 1;\\n            if (labelLen == 0) {\\n                break;\\n            }\\n        }\\n        return idx - offset;\\n    }\\n\\n    /**\\n     * @dev Returns a DNS format name at the specified offset of self.\\n     * @param self The byte array to read a name from.\\n     * @param offset The offset to start reading at.\\n     * @return ret The name.\\n     */\\n    function readName(\\n        bytes memory self,\\n        uint256 offset\\n    ) internal pure returns (bytes memory ret) {\\n        uint256 len = nameLength(self, offset);\\n        return self.substring(offset, len);\\n    }\\n\\n    /**\\n     * @dev Returns the number of labels in the DNS name at 'offset' in 'self'.\\n     * @param self The byte array to read a name from.\\n     * @param offset The offset to start reading at.\\n     * @return The number of labels in the DNS name at 'offset', in bytes.\\n     */\\n    function labelCount(\\n        bytes memory self,\\n        uint256 offset\\n    ) internal pure returns (uint256) {\\n        uint256 count = 0;\\n        while (true) {\\n            assert(offset < self.length);\\n            uint256 labelLen = self.readUint8(offset);\\n            offset += labelLen + 1;\\n            if (labelLen == 0) {\\n                break;\\n            }\\n            count += 1;\\n        }\\n        return count;\\n    }\\n\\n    uint256 constant RRSIG_TYPE = 0;\\n    uint256 constant RRSIG_ALGORITHM = 2;\\n    uint256 constant RRSIG_LABELS = 3;\\n    uint256 constant RRSIG_TTL = 4;\\n    uint256 constant RRSIG_EXPIRATION = 8;\\n    uint256 constant RRSIG_INCEPTION = 12;\\n    uint256 constant RRSIG_KEY_TAG = 16;\\n    uint256 constant RRSIG_SIGNER_NAME = 18;\\n\\n    struct SignedSet {\\n        uint16 typeCovered;\\n        uint8 algorithm;\\n        uint8 labels;\\n        uint32 ttl;\\n        uint32 expiration;\\n        uint32 inception;\\n        uint16 keytag;\\n        bytes signerName;\\n        bytes data;\\n        bytes name;\\n    }\\n\\n    function readSignedSet(\\n        bytes memory data\\n    ) internal pure returns (SignedSet memory self) {\\n        self.typeCovered = data.readUint16(RRSIG_TYPE);\\n        self.algorithm = data.readUint8(RRSIG_ALGORITHM);\\n        self.labels = data.readUint8(RRSIG_LABELS);\\n        self.ttl = data.readUint32(RRSIG_TTL);\\n        self.expiration = data.readUint32(RRSIG_EXPIRATION);\\n        self.inception = data.readUint32(RRSIG_INCEPTION);\\n        self.keytag = data.readUint16(RRSIG_KEY_TAG);\\n        self.signerName = readName(data, RRSIG_SIGNER_NAME);\\n        self.data = data.substring(\\n            RRSIG_SIGNER_NAME + self.signerName.length,\\n            data.length - RRSIG_SIGNER_NAME - self.signerName.length\\n        );\\n    }\\n\\n    function rrs(\\n        SignedSet memory rrset\\n    ) internal pure returns (RRIterator memory) {\\n        return iterateRRs(rrset.data, 0);\\n    }\\n\\n    /**\\n     * @dev An iterator over resource records.\\n     */\\n    struct RRIterator {\\n        bytes data;\\n        uint256 offset;\\n        uint16 dnstype;\\n        uint16 class;\\n        uint32 ttl;\\n        uint256 rdataOffset;\\n        uint256 nextOffset;\\n    }\\n\\n    /**\\n     * @dev Begins iterating over resource records.\\n     * @param self The byte string to read from.\\n     * @param offset The offset to start reading at.\\n     * @return ret An iterator object.\\n     */\\n    function iterateRRs(\\n        bytes memory self,\\n        uint256 offset\\n    ) internal pure returns (RRIterator memory ret) {\\n        ret.data = self;\\n        ret.nextOffset = offset;\\n        next(ret);\\n    }\\n\\n    /**\\n     * @dev Returns true iff there are more RRs to iterate.\\n     * @param iter The iterator to check.\\n     * @return True iff the iterator has finished.\\n     */\\n    function done(RRIterator memory iter) internal pure returns (bool) {\\n        return iter.offset >= iter.data.length;\\n    }\\n\\n    /**\\n     * @dev Moves the iterator to the next resource record.\\n     * @param iter The iterator to advance.\\n     */\\n    function next(RRIterator memory iter) internal pure {\\n        iter.offset = iter.nextOffset;\\n        if (iter.offset >= iter.data.length) {\\n            return;\\n        }\\n\\n        // Skip the name\\n        uint256 off = iter.offset + nameLength(iter.data, iter.offset);\\n\\n        // Read type, class, and ttl\\n        iter.dnstype = iter.data.readUint16(off);\\n        off += 2;\\n        iter.class = iter.data.readUint16(off);\\n        off += 2;\\n        iter.ttl = iter.data.readUint32(off);\\n        off += 4;\\n\\n        // Read the rdata\\n        uint256 rdataLength = iter.data.readUint16(off);\\n        off += 2;\\n        iter.rdataOffset = off;\\n        iter.nextOffset = off + rdataLength;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the current record.\\n     * @param iter The iterator.\\n     * @return A new bytes object containing the owner name from the RR.\\n     */\\n    function name(RRIterator memory iter) internal pure returns (bytes memory) {\\n        return\\n            iter.data.substring(\\n                iter.offset,\\n                nameLength(iter.data, iter.offset)\\n            );\\n    }\\n\\n    /**\\n     * @dev Returns the rdata portion of the current record.\\n     * @param iter The iterator.\\n     * @return A new bytes object containing the RR's RDATA.\\n     */\\n    function rdata(\\n        RRIterator memory iter\\n    ) internal pure returns (bytes memory) {\\n        return\\n            iter.data.substring(\\n                iter.rdataOffset,\\n                iter.nextOffset - iter.rdataOffset\\n            );\\n    }\\n\\n    uint256 constant DNSKEY_FLAGS = 0;\\n    uint256 constant DNSKEY_PROTOCOL = 2;\\n    uint256 constant DNSKEY_ALGORITHM = 3;\\n    uint256 constant DNSKEY_PUBKEY = 4;\\n\\n    struct DNSKEY {\\n        uint16 flags;\\n        uint8 protocol;\\n        uint8 algorithm;\\n        bytes publicKey;\\n    }\\n\\n    function readDNSKEY(\\n        bytes memory data,\\n        uint256 offset,\\n        uint256 length\\n    ) internal pure returns (DNSKEY memory self) {\\n        self.flags = data.readUint16(offset + DNSKEY_FLAGS);\\n        self.protocol = data.readUint8(offset + DNSKEY_PROTOCOL);\\n        self.algorithm = data.readUint8(offset + DNSKEY_ALGORITHM);\\n        self.publicKey = data.substring(\\n            offset + DNSKEY_PUBKEY,\\n            length - DNSKEY_PUBKEY\\n        );\\n    }\\n\\n    uint256 constant DS_KEY_TAG = 0;\\n    uint256 constant DS_ALGORITHM = 2;\\n    uint256 constant DS_DIGEST_TYPE = 3;\\n    uint256 constant DS_DIGEST = 4;\\n\\n    struct DS {\\n        uint16 keytag;\\n        uint8 algorithm;\\n        uint8 digestType;\\n        bytes digest;\\n    }\\n\\n    function readDS(\\n        bytes memory data,\\n        uint256 offset,\\n        uint256 length\\n    ) internal pure returns (DS memory self) {\\n        self.keytag = data.readUint16(offset + DS_KEY_TAG);\\n        self.algorithm = data.readUint8(offset + DS_ALGORITHM);\\n        self.digestType = data.readUint8(offset + DS_DIGEST_TYPE);\\n        self.digest = data.substring(offset + DS_DIGEST, length - DS_DIGEST);\\n    }\\n\\n    function isSubdomainOf(\\n        bytes memory self,\\n        bytes memory other\\n    ) internal pure returns (bool) {\\n        uint256 off = 0;\\n        uint256 counts = labelCount(self, 0);\\n        uint256 othercounts = labelCount(other, 0);\\n\\n        while (counts > othercounts) {\\n            off = progress(self, off);\\n            counts--;\\n        }\\n\\n        return self.equals(off, other, 0);\\n    }\\n\\n    function compareNames(\\n        bytes memory self,\\n        bytes memory other\\n    ) internal pure returns (int256) {\\n        if (self.equals(other)) {\\n            return 0;\\n        }\\n\\n        uint256 off;\\n        uint256 otheroff;\\n        uint256 prevoff;\\n        uint256 otherprevoff;\\n        uint256 counts = labelCount(self, 0);\\n        uint256 othercounts = labelCount(other, 0);\\n\\n        // Keep removing labels from the front of the name until both names are equal length\\n        while (counts > othercounts) {\\n            prevoff = off;\\n            off = progress(self, off);\\n            counts--;\\n        }\\n\\n        while (othercounts > counts) {\\n            otherprevoff = otheroff;\\n            otheroff = progress(other, otheroff);\\n            othercounts--;\\n        }\\n\\n        // Compare the last nonequal labels to each other\\n        while (counts > 0 && !self.equals(off, other, otheroff)) {\\n            prevoff = off;\\n            off = progress(self, off);\\n            otherprevoff = otheroff;\\n            otheroff = progress(other, otheroff);\\n            counts -= 1;\\n        }\\n\\n        if (off == 0) {\\n            return -1;\\n        }\\n        if (otheroff == 0) {\\n            return 1;\\n        }\\n\\n        return\\n            self.compare(\\n                prevoff + 1,\\n                self.readUint8(prevoff),\\n                other,\\n                otherprevoff + 1,\\n                other.readUint8(otherprevoff)\\n            );\\n    }\\n\\n    /**\\n     * @dev Compares two serial numbers using RFC1982 serial number math.\\n     */\\n    function serialNumberGte(\\n        uint32 i1,\\n        uint32 i2\\n    ) internal pure returns (bool) {\\n        unchecked {\\n            return int32(i1) - int32(i2) >= 0;\\n        }\\n    }\\n\\n    function progress(\\n        bytes memory body,\\n        uint256 off\\n    ) internal pure returns (uint256) {\\n        return off + 1 + body.readUint8(off);\\n    }\\n\\n    /**\\n     * @dev Computes the keytag for a chunk of data.\\n     * @param data The data to compute a keytag for.\\n     * @return The computed key tag.\\n     */\\n    function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n        /* This function probably deserves some explanation.\\n         * The DNSSEC keytag function is a checksum that relies on summing up individual bytes\\n         * from the input string, with some mild bitshifting. Here's a Naive solidity implementation:\\n         *\\n         *     function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n         *         uint ac;\\n         *         for (uint i = 0; i < data.length; i++) {\\n         *             ac += i & 1 == 0 ? uint16(data.readUint8(i)) << 8 : data.readUint8(i);\\n         *         }\\n         *         return uint16(ac + (ac >> 16));\\n         *     }\\n         *\\n         * The EVM, with its 256 bit words, is exceedingly inefficient at doing byte-by-byte operations;\\n         * the code above, on reasonable length inputs, consumes over 100k gas. But we can make the EVM's\\n         * large words work in our favour.\\n         *\\n         * The code below works by treating the input as a series of 256 bit words. It first masks out\\n         * even and odd bytes from each input word, adding them to two separate accumulators `ac1` and `ac2`.\\n         * The bytes are separated by empty bytes, so as long as no individual sum exceeds 2^16-1, we're\\n         * effectively summing 16 different numbers with each EVM ADD opcode.\\n         *\\n         * Once it's added up all the inputs, it has to add all the 16 bit values in `ac1` and `ac2` together.\\n         * It does this using the same trick - mask out every other value, shift to align them, add them together.\\n         * After the first addition on both accumulators, there's enough room to add the two accumulators together,\\n         * and the remaining sums can be done just on ac1.\\n         */\\n        unchecked {\\n            require(data.length <= 8192, \\\"Long keys not permitted\\\");\\n            uint256 ac1;\\n            uint256 ac2;\\n            for (uint256 i = 0; i < data.length + 31; i += 32) {\\n                uint256 word;\\n                assembly {\\n                    word := mload(add(add(data, 32), i))\\n                }\\n                if (i + 32 > data.length) {\\n                    uint256 unused = 256 - (data.length - i) * 8;\\n                    word = (word >> unused) << unused;\\n                }\\n                ac1 +=\\n                    (word &\\n                        0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >>\\n                    8;\\n                ac2 += (word &\\n                    0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF);\\n            }\\n            ac1 =\\n                (ac1 &\\n                    0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n                ((ac1 &\\n                    0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n                    16);\\n            ac2 =\\n                (ac2 &\\n                    0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n                ((ac2 &\\n                    0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n                    16);\\n            ac1 = (ac1 << 8) + ac2;\\n            ac1 =\\n                (ac1 &\\n                    0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) +\\n                ((ac1 &\\n                    0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >>\\n                    32);\\n            ac1 =\\n                (ac1 &\\n                    0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) +\\n                ((ac1 &\\n                    0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >>\\n                    64);\\n            ac1 =\\n                (ac1 &\\n                    0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +\\n                (ac1 >> 128);\\n            ac1 += (ac1 >> 16) & 0xFFFF;\\n            return uint16(ac1);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x4dd68a6efd7c38f6b0e95ca0c056ecb74f88583da650b1a8639e6e78be36fede\"},\"contracts/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(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xaf6825f9852c69f8e36540821d067b4550dd2263497af9d645309b6a0c457ba6\"},\"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(\\n        bytes calldata data,\\n        bytes calldata hash\\n    ) external pure virtual returns (bool);\\n}\\n\",\"keccak256\":\"0x8ea926b2db0578c4ad7fce4582fc0f6f0f9efee8dca2085dbdb9984f18941e28\"}},\"version\":1}",
  "bytecode": "0x60806040523480156200001157600080fd5b506040516200205638038062002056833981016040819052620000349162000072565b600180546001600160a01b031916331790556000620000548282620001d6565b5050620002a2565b634e487b7160e01b600052604160045260246000fd5b600060208083850312156200008657600080fd5b82516001600160401b03808211156200009e57600080fd5b818501915085601f830112620000b357600080fd5b815181811115620000c857620000c86200005c565b604051601f8201601f19908116603f01168101908382118183101715620000f357620000f36200005c565b8160405282815288868487010111156200010c57600080fd5b600093505b8284101562000130578484018601518185018701529285019262000111565b600086848301015280965050505050505092915050565b600181811c908216806200015c57607f821691505b6020821081036200017d57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001d157600081815260208120601f850160051c81016020861015620001ac5750805b601f850160051c820191505b81811015620001cd57828155600101620001b8565b5050505b505050565b81516001600160401b03811115620001f257620001f26200005c565b6200020a8162000203845462000147565b8462000183565b602080601f831160018114620002425760008415620002295750858301515b600019600386901b1c1916600185901b178555620001cd565b600085815260208120601f198616915b82811015620002735788860151825594840194600190910190840162000252565b5085821015620002925787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b611da480620002b26000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c806373cc48a61161007657806398d35f201161005b57806398d35f2014610161578063bdf95fef14610176578063c327deef1461018957600080fd5b806373cc48a61461010d5780638da5cb5b1461014e57600080fd5b8063020ed8d3146100a857806313af4035146100bd57806328e7677d146100d0578063440f3d42146100e3575b600080fd5b6100bb6100b6366004611871565b6101b2565b005b6100bb6100cb3660046118a8565b610241565b6100bb6100de366004611871565b610287565b6100f66100f1366004611a9f565b61030e565b604051610104929190611b2a565b60405180910390f35b61013661011b366004611b52565b6003602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610104565b600154610136906001600160a01b031681565b610169610400565b6040516101049190611b6d565b6100f6610184366004611b80565b61048e565b610136610197366004611b52565b6002602052600090815260409020546001600160a01b031681565b6001546001600160a01b031633146101c957600080fd5b60ff8216600081815260026020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0386169081179091558251938452908301527ff73c3c226af96b7f1ba666a21b3ceaf2be3ee6a365e3178fd9cd1eaae0075aa891015b60405180910390a15050565b6001546001600160a01b0316331461025857600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001546001600160a01b0316331461029e57600080fd5b60ff8216600081815260036020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0386169081179091558251938452908301527f2fcc274c3b72dd483ab201bfa87295e3817e8b9b10693219873b722ca1af00c79101610235565b60606000806000805461032090611bb5565b80601f016020809104026020016040519081016040528092919081815260200182805461034c90611bb5565b80156103995780601f1061036e57610100808354040283529160200191610399565b820191906000526020600020905b81548152906001019060200180831161037c57829003601f168201915b5050505050905060005b85518110156103f65760006103d28783815181106103c3576103c3611bef565b602002602001015184886104a5565b61010081015160a090910151945092508190506103ee81611c1b565b9150506103a3565b5091509250929050565b6000805461040d90611bb5565b80601f016020809104026020016040519081016040528092919081815260200182805461043990611bb5565b80156104865780601f1061045b57610100808354040283529160200191610486565b820191906000526020600020905b81548152906001019060200180831161046957829003601f168201915b505050505081565b6060600061049c834261030e565b91509150915091565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c082019290925260e081018290526101008101829052610120810191909152835161050390610647565b90506000610515828360000151610789565b604083015190915060ff1661052b8260006108e6565b14610573578082604001516040517fe861b2bd00000000000000000000000000000000000000000000000000000000815260040161056a929190611c34565b60405180910390fd5b6101208201819052608082015160009084900360030b12156105d75760808201516040517fa784f87e00000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161056a565b60a0820151600090840360030b12156106325760a08201516040517fbd41036a00000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161056a565b61063e8183878761094c565b505b9392505050565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018190526101008201819052610120820152906106a2908390610a16565b61ffff1681526106b3826002610a3e565b60ff1660208201526106c6826003610a3e565b60ff1660408201526106d9826004610a62565b63ffffffff90811660608301526106f5908390600890610a6216565b63ffffffff9081166080830152610711908390600c90610a6216565b63ffffffff90811660a083015261072d908390601090610a1616565b61ffff1660c0820152610741826012610a8c565b60e082018190525161077e90610758906012611c59565b8260e00151516012855161076c9190611c6c565b6107769190611c6c565b849190610aaf565b610100820152919050565b6060600061079684610b31565b90505b805151602082015110156108df57606081015161ffff166001146107f55760608101516040517f98a5f31a00000000000000000000000000000000000000000000000000000000815261ffff909116600482015260240161056a565b815160000361080e5761080781610b8f565b9150610878565b6020810151815161081e91610bb0565b8251141580610841575080516020820151835161083f928592600092610c0a565b155b15610878576040517fcbceee6f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8261ffff16816040015161ffff16146108d15760408082015190517fa6ff8a8a00000000000000000000000000000000000000000000000000000000815261ffff9182166004820152908416602482015260440161056a565b6108da81610c2d565b610799565b5092915050565b6000805b835183106108fa576108fa611c7f565b60006109068585610a3e565b60ff169050610916816001611c59565b6109209085611c59565b9350806000036109305750610943565b61093b600183611c59565b9150506108ea565b90505b92915050565b60e083015161095c908590610d15565b6109995760e08301516040517feaafc59b00000000000000000000000000000000000000000000000000000000815261056a918691600401611c95565b60006109a58282610d72565b9050602b61ffff16816040015161ffff16036109cb576109c6848483610dd3565b610a0f565b603061ffff16816040015161ffff16036109ea576109c6848483610ec0565b60408082015190516361529e8760e01b815261ffff909116600482015260240161056a565b5050505050565b8151600090610a26836002611c59565b1115610a3157600080fd5b50016002015161ffff1690565b6000828281518110610a5257610a52611bef565b016020015160f81c905092915050565b8151600090610a72836004611c59565b1115610a7d57600080fd5b50016004015163ffffffff1690565b60606000610a9a8484610bb0565b9050610aa7848483610aaf565b949350505050565b8251606090610abe8385611c59565b1115610ac957600080fd5b60008267ffffffffffffffff811115610ae457610ae46118c5565b6040519080825280601f01601f191660200182016040528015610b0e576020820181803683370190505b50905060208082019086860101610b26828287610f88565b509095945050505050565b610b7f6040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b6109468261010001516000610d72565b6020810151815160609161094691610ba79082610bb0565b84519190610aaf565b6000815b83518110610bc457610bc4611c7f565b6000610bd08583610a3e565b60ff169050610be0816001611c59565b610bea9083611c59565b915080600003610bfa5750610c00565b50610bb4565b610aa78382611c6c565b6000610c17848484610fde565b610c22878785610fde565b149695505050505050565b60c08101516020820181905281515111610c445750565b6000610c5882600001518360200151610bb0565b8260200151610c679190611c59565b8251909150610c769082610a16565b61ffff166040830152610c8a600282611c59565b8251909150610c999082610a16565b61ffff166060830152610cad600282611c59565b8251909150610cbc9082610a62565b63ffffffff166080830152610cd2600482611c59565b8251909150600090610ce49083610a16565b61ffff169050610cf5600283611c59565b60a084018190529150610d088183611c59565b60c0909301929092525050565b60008080610d2385826108e6565b90506000610d328560006108e6565b90505b80821115610d5b57610d478684611002565b925081610d5381611cc3565b925050610d35565b610d688684876000611026565b9695505050505050565b610dc06040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261094681610c2d565b60208101516000610de385610b31565b90505b80515160208201511015610ea057604081015161ffff16603014610e295760408082015190516361529e8760e01b815261ffff909116600482015260240161056a565b6000610e348261105b565b90506000610e4f60008351846110779092919063ffffffff16565b9050610e5d81838989611115565b15610e9057610e728760e00151868385611254565b15610e805750505050505050565b60c08501849052610e9085610c2d565b5050610e9b81610c2d565b610de6565b508360e001516040516306cde0f360e01b815260040161056a9190611b6d565b80515160208201511015610f69576000610ed982610b8f565b9050610ef28460e001518261139190919063ffffffff16565b610f17578360e0015181604051636b80573f60e11b815260040161056a929190611c95565b6000610f228361105b565b90506000610f3d60008351846110779092919063ffffffff16565b9050610f4b81838888611115565b15610f5857505050505050565b505050610f6481610c2d565b610ec0565b8260e001516040516306cde0f360e01b815260040161056a9190611b6d565b60208110610fc05781518352610f9f602084611c59565b9250610fac602083611c59565b9150610fb9602082611c6c565b9050610f88565b905182516020929092036101000a6000190180199091169116179052565b8251600090610fed8385611c59565b1115610ff857600080fd5b5091016020012090565b600061100e8383610a3e565b60ff1661101c836001611c59565b6109439190611c59565b600061103f838384865161103a9190611c6c565b610fde565b611051868687895161103a9190611c6c565b1495945050505050565b60a081015160c082015160609161094691610ba7908290611c6c565b60408051608081018252600080825260208201819052918101919091526060808201526110af6110a8600085611c59565b8590610a16565b61ffff1681526110ca6110c3600285611c59565b8590610a3e565b60ff1660208201526110e06110c3600385611c59565b60ff1660408201526111096110f6600485611c59565b611101600485611c6c565b869190610aaf565b60608201529392505050565b6000846020015160ff1660031461112e57506000610aa7565b826020015160ff16856040015160ff161461114b57506000610aa7565b6000611156856113af565b90508360c0015161ffff168161ffff1614611175576000915050610aa7565b85516101001660000361118c576000915050610aa7565b60408087015160ff166000908152600260205220546001600160a01b0316806111ba57600092505050610aa7565b835160208501516040517fde8f50a10000000000000000000000000000000000000000000000000000000081526001600160a01b0384169263de8f50a192611208928b929190600401611cda565b602060405180830381865afa158015611225573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112499190611d13565b979650505050505050565b600080611260836113af565b90505b8451516020860151101561138557600061127c86610b8f565b90506112888188611391565b6112a9578681604051636b80573f60e11b815260040161056a929190611c95565b60a086015160c08701516000916112ce916112c5908290611c6c565b89519190611077565b90508261ffff16816000015161ffff16146112ea575050611377565b856040015160ff16816020015160ff1614611306575050611377565b60408051808201909152606081526000602082015261133386518a5161132c9190611c59565b82906115f3565b5061133e818a61166a565b50611349818761166a565b5061136182604001518260000151846060015161168b565b15611373576001945050505050610aa7565b5050505b61138085610c2d565b611263565b50600095945050505050565b60008151835114801561094357506109438360008460008751610c0a565b60006120008251111561141e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4c6f6e67206b657973206e6f74207065726d6974746564000000000000000000604482015260640161056a565b60008060005b8451601f0181101561149357600081602087010151905085518260200111156114595785518290036008026101000390811c901b5b7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff600882901c81169490940193169190910190602001611424565b506010827fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff000016901c827dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff160191506010817fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff000016901c817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff1601905080600883901b0191506020827fffffffff00000000ffffffff00000000ffffffff00000000ffffffff0000000016901c827bffffffff00000000ffffffff00000000ffffffff00000000ffffffff160191506040827fffffffffffffffff0000000000000000ffffffffffffffff000000000000000016901c8277ffffffffffffffff0000000000000000ffffffffffffffff16019150608082901c826fffffffffffffffffffffffffffffffff16019150601082901c61ffff16820191508192505050919050565b604080518082019091526060815260006020820152611613602083611d35565b1561163b57611623602083611d35565b61162e906020611c6c565b6116389083611c59565b91505b60208084018390526040518085526000815290818401018181101561165f57600080fd5b604052509192915050565b60408051808201909152606081526000602082015261094383838451611750565b60ff83166000908152600360205260408120546001600160a01b03166116b357506000610640565b60ff8416600090815260036020526040908190205490517ff7e83aee0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063f7e83aee9061170f9086908690600401611c95565b602060405180830381865afa15801561172c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa79190611d13565b604080518082019091526060815260006020820152825182111561177357600080fd5b83515160006117828483611c59565b905085602001518111156117a4576117a48661179f836002611d57565b611826565b8551805183820160200191600091808511156117be578482525b505050602086015b602086106117fe57805182526117dd602083611c59565b91506117ea602082611c59565b90506117f7602087611c6c565b95506117c6565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b815161183283836115f3565b5061183d838261166a565b50505050565b803560ff8116811461185457600080fd5b919050565b6001600160a01b038116811461186e57600080fd5b50565b6000806040838503121561188457600080fd5b61188d83611843565b9150602083013561189d81611859565b809150509250929050565b6000602082840312156118ba57600080fd5b813561094381611859565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156118fe576118fe6118c5565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561192d5761192d6118c5565b604052919050565b600082601f83011261194657600080fd5b813567ffffffffffffffff811115611960576119606118c5565b611973601f8201601f1916602001611904565b81815284602083860101111561198857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126119b657600080fd5b8135602067ffffffffffffffff808311156119d3576119d36118c5565b8260051b6119e2838201611904565b93845285810183019383810190888611156119fc57600080fd5b84880192505b85831015611a9357823584811115611a1a5760008081fd5b88016040818b03601f1901811315611a325760008081fd5b611a3a6118db565b8783013587811115611a4c5760008081fd5b611a5a8d8a83870101611935565b825250908201359086821115611a705760008081fd5b611a7e8c8984860101611935565b81890152845250509184019190840190611a02565b98975050505050505050565b60008060408385031215611ab257600080fd5b823567ffffffffffffffff811115611ac957600080fd5b611ad5858286016119a5565b95602094909401359450505050565b6000815180845260005b81811015611b0a57602081850181015186830182015201611aee565b506000602082860101526020601f19601f83011685010191505092915050565b604081526000611b3d6040830185611ae4565b905063ffffffff831660208301529392505050565b600060208284031215611b6457600080fd5b61094382611843565b6020815260006109436020830184611ae4565b600060208284031215611b9257600080fd5b813567ffffffffffffffff811115611ba957600080fd5b610aa7848285016119a5565b600181811c90821680611bc957607f821691505b602082108103611be957634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611c2d57611c2d611c05565b5060010190565b604081526000611c476040830185611ae4565b905060ff831660208301529392505050565b8082018082111561094657610946611c05565b8181038181111561094657610946611c05565b634e487b7160e01b600052600160045260246000fd5b604081526000611ca86040830185611ae4565b8281036020840152611cba8185611ae4565b95945050505050565b600081611cd257611cd2611c05565b506000190190565b606081526000611ced6060830186611ae4565b8281036020840152611cff8186611ae4565b90508281036040840152610d688185611ae4565b600060208284031215611d2557600080fd5b8151801515811461094357600080fd5b600082611d5257634e487b7160e01b600052601260045260246000fd5b500690565b808202811582820484141761094657610946611c0556fea2646970667358221220a36fa1213f53338776d2c9565e9a8b3482299a2c13495ac6aaeebf00585273ff64736f6c63430008110033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a35760003560e01c806373cc48a61161007657806398d35f201161005b57806398d35f2014610161578063bdf95fef14610176578063c327deef1461018957600080fd5b806373cc48a61461010d5780638da5cb5b1461014e57600080fd5b8063020ed8d3146100a857806313af4035146100bd57806328e7677d146100d0578063440f3d42146100e3575b600080fd5b6100bb6100b6366004611871565b6101b2565b005b6100bb6100cb3660046118a8565b610241565b6100bb6100de366004611871565b610287565b6100f66100f1366004611a9f565b61030e565b604051610104929190611b2a565b60405180910390f35b61013661011b366004611b52565b6003602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610104565b600154610136906001600160a01b031681565b610169610400565b6040516101049190611b6d565b6100f6610184366004611b80565b61048e565b610136610197366004611b52565b6002602052600090815260409020546001600160a01b031681565b6001546001600160a01b031633146101c957600080fd5b60ff8216600081815260026020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0386169081179091558251938452908301527ff73c3c226af96b7f1ba666a21b3ceaf2be3ee6a365e3178fd9cd1eaae0075aa891015b60405180910390a15050565b6001546001600160a01b0316331461025857600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001546001600160a01b0316331461029e57600080fd5b60ff8216600081815260036020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0386169081179091558251938452908301527f2fcc274c3b72dd483ab201bfa87295e3817e8b9b10693219873b722ca1af00c79101610235565b60606000806000805461032090611bb5565b80601f016020809104026020016040519081016040528092919081815260200182805461034c90611bb5565b80156103995780601f1061036e57610100808354040283529160200191610399565b820191906000526020600020905b81548152906001019060200180831161037c57829003601f168201915b5050505050905060005b85518110156103f65760006103d28783815181106103c3576103c3611bef565b602002602001015184886104a5565b61010081015160a090910151945092508190506103ee81611c1b565b9150506103a3565b5091509250929050565b6000805461040d90611bb5565b80601f016020809104026020016040519081016040528092919081815260200182805461043990611bb5565b80156104865780601f1061045b57610100808354040283529160200191610486565b820191906000526020600020905b81548152906001019060200180831161046957829003601f168201915b505050505081565b6060600061049c834261030e565b91509150915091565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c082019290925260e081018290526101008101829052610120810191909152835161050390610647565b90506000610515828360000151610789565b604083015190915060ff1661052b8260006108e6565b14610573578082604001516040517fe861b2bd00000000000000000000000000000000000000000000000000000000815260040161056a929190611c34565b60405180910390fd5b6101208201819052608082015160009084900360030b12156105d75760808201516040517fa784f87e00000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161056a565b60a0820151600090840360030b12156106325760a08201516040517fbd41036a00000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161056a565b61063e8183878761094c565b505b9392505050565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018190526101008201819052610120820152906106a2908390610a16565b61ffff1681526106b3826002610a3e565b60ff1660208201526106c6826003610a3e565b60ff1660408201526106d9826004610a62565b63ffffffff90811660608301526106f5908390600890610a6216565b63ffffffff9081166080830152610711908390600c90610a6216565b63ffffffff90811660a083015261072d908390601090610a1616565b61ffff1660c0820152610741826012610a8c565b60e082018190525161077e90610758906012611c59565b8260e00151516012855161076c9190611c6c565b6107769190611c6c565b849190610aaf565b610100820152919050565b6060600061079684610b31565b90505b805151602082015110156108df57606081015161ffff166001146107f55760608101516040517f98a5f31a00000000000000000000000000000000000000000000000000000000815261ffff909116600482015260240161056a565b815160000361080e5761080781610b8f565b9150610878565b6020810151815161081e91610bb0565b8251141580610841575080516020820151835161083f928592600092610c0a565b155b15610878576040517fcbceee6f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8261ffff16816040015161ffff16146108d15760408082015190517fa6ff8a8a00000000000000000000000000000000000000000000000000000000815261ffff9182166004820152908416602482015260440161056a565b6108da81610c2d565b610799565b5092915050565b6000805b835183106108fa576108fa611c7f565b60006109068585610a3e565b60ff169050610916816001611c59565b6109209085611c59565b9350806000036109305750610943565b61093b600183611c59565b9150506108ea565b90505b92915050565b60e083015161095c908590610d15565b6109995760e08301516040517feaafc59b00000000000000000000000000000000000000000000000000000000815261056a918691600401611c95565b60006109a58282610d72565b9050602b61ffff16816040015161ffff16036109cb576109c6848483610dd3565b610a0f565b603061ffff16816040015161ffff16036109ea576109c6848483610ec0565b60408082015190516361529e8760e01b815261ffff909116600482015260240161056a565b5050505050565b8151600090610a26836002611c59565b1115610a3157600080fd5b50016002015161ffff1690565b6000828281518110610a5257610a52611bef565b016020015160f81c905092915050565b8151600090610a72836004611c59565b1115610a7d57600080fd5b50016004015163ffffffff1690565b60606000610a9a8484610bb0565b9050610aa7848483610aaf565b949350505050565b8251606090610abe8385611c59565b1115610ac957600080fd5b60008267ffffffffffffffff811115610ae457610ae46118c5565b6040519080825280601f01601f191660200182016040528015610b0e576020820181803683370190505b50905060208082019086860101610b26828287610f88565b509095945050505050565b610b7f6040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b6109468261010001516000610d72565b6020810151815160609161094691610ba79082610bb0565b84519190610aaf565b6000815b83518110610bc457610bc4611c7f565b6000610bd08583610a3e565b60ff169050610be0816001611c59565b610bea9083611c59565b915080600003610bfa5750610c00565b50610bb4565b610aa78382611c6c565b6000610c17848484610fde565b610c22878785610fde565b149695505050505050565b60c08101516020820181905281515111610c445750565b6000610c5882600001518360200151610bb0565b8260200151610c679190611c59565b8251909150610c769082610a16565b61ffff166040830152610c8a600282611c59565b8251909150610c999082610a16565b61ffff166060830152610cad600282611c59565b8251909150610cbc9082610a62565b63ffffffff166080830152610cd2600482611c59565b8251909150600090610ce49083610a16565b61ffff169050610cf5600283611c59565b60a084018190529150610d088183611c59565b60c0909301929092525050565b60008080610d2385826108e6565b90506000610d328560006108e6565b90505b80821115610d5b57610d478684611002565b925081610d5381611cc3565b925050610d35565b610d688684876000611026565b9695505050505050565b610dc06040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261094681610c2d565b60208101516000610de385610b31565b90505b80515160208201511015610ea057604081015161ffff16603014610e295760408082015190516361529e8760e01b815261ffff909116600482015260240161056a565b6000610e348261105b565b90506000610e4f60008351846110779092919063ffffffff16565b9050610e5d81838989611115565b15610e9057610e728760e00151868385611254565b15610e805750505050505050565b60c08501849052610e9085610c2d565b5050610e9b81610c2d565b610de6565b508360e001516040516306cde0f360e01b815260040161056a9190611b6d565b80515160208201511015610f69576000610ed982610b8f565b9050610ef28460e001518261139190919063ffffffff16565b610f17578360e0015181604051636b80573f60e11b815260040161056a929190611c95565b6000610f228361105b565b90506000610f3d60008351846110779092919063ffffffff16565b9050610f4b81838888611115565b15610f5857505050505050565b505050610f6481610c2d565b610ec0565b8260e001516040516306cde0f360e01b815260040161056a9190611b6d565b60208110610fc05781518352610f9f602084611c59565b9250610fac602083611c59565b9150610fb9602082611c6c565b9050610f88565b905182516020929092036101000a6000190180199091169116179052565b8251600090610fed8385611c59565b1115610ff857600080fd5b5091016020012090565b600061100e8383610a3e565b60ff1661101c836001611c59565b6109439190611c59565b600061103f838384865161103a9190611c6c565b610fde565b611051868687895161103a9190611c6c565b1495945050505050565b60a081015160c082015160609161094691610ba7908290611c6c565b60408051608081018252600080825260208201819052918101919091526060808201526110af6110a8600085611c59565b8590610a16565b61ffff1681526110ca6110c3600285611c59565b8590610a3e565b60ff1660208201526110e06110c3600385611c59565b60ff1660408201526111096110f6600485611c59565b611101600485611c6c565b869190610aaf565b60608201529392505050565b6000846020015160ff1660031461112e57506000610aa7565b826020015160ff16856040015160ff161461114b57506000610aa7565b6000611156856113af565b90508360c0015161ffff168161ffff1614611175576000915050610aa7565b85516101001660000361118c576000915050610aa7565b60408087015160ff166000908152600260205220546001600160a01b0316806111ba57600092505050610aa7565b835160208501516040517fde8f50a10000000000000000000000000000000000000000000000000000000081526001600160a01b0384169263de8f50a192611208928b929190600401611cda565b602060405180830381865afa158015611225573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112499190611d13565b979650505050505050565b600080611260836113af565b90505b8451516020860151101561138557600061127c86610b8f565b90506112888188611391565b6112a9578681604051636b80573f60e11b815260040161056a929190611c95565b60a086015160c08701516000916112ce916112c5908290611c6c565b89519190611077565b90508261ffff16816000015161ffff16146112ea575050611377565b856040015160ff16816020015160ff1614611306575050611377565b60408051808201909152606081526000602082015261133386518a5161132c9190611c59565b82906115f3565b5061133e818a61166a565b50611349818761166a565b5061136182604001518260000151846060015161168b565b15611373576001945050505050610aa7565b5050505b61138085610c2d565b611263565b50600095945050505050565b60008151835114801561094357506109438360008460008751610c0a565b60006120008251111561141e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4c6f6e67206b657973206e6f74207065726d6974746564000000000000000000604482015260640161056a565b60008060005b8451601f0181101561149357600081602087010151905085518260200111156114595785518290036008026101000390811c901b5b7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff600882901c81169490940193169190910190602001611424565b506010827fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff000016901c827dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff160191506010817fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff000016901c817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff1601905080600883901b0191506020827fffffffff00000000ffffffff00000000ffffffff00000000ffffffff0000000016901c827bffffffff00000000ffffffff00000000ffffffff00000000ffffffff160191506040827fffffffffffffffff0000000000000000ffffffffffffffff000000000000000016901c8277ffffffffffffffff0000000000000000ffffffffffffffff16019150608082901c826fffffffffffffffffffffffffffffffff16019150601082901c61ffff16820191508192505050919050565b604080518082019091526060815260006020820152611613602083611d35565b1561163b57611623602083611d35565b61162e906020611c6c565b6116389083611c59565b91505b60208084018390526040518085526000815290818401018181101561165f57600080fd5b604052509192915050565b60408051808201909152606081526000602082015261094383838451611750565b60ff83166000908152600360205260408120546001600160a01b03166116b357506000610640565b60ff8416600090815260036020526040908190205490517ff7e83aee0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063f7e83aee9061170f9086908690600401611c95565b602060405180830381865afa15801561172c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa79190611d13565b604080518082019091526060815260006020820152825182111561177357600080fd5b83515160006117828483611c59565b905085602001518111156117a4576117a48661179f836002611d57565b611826565b8551805183820160200191600091808511156117be578482525b505050602086015b602086106117fe57805182526117dd602083611c59565b91506117ea602082611c59565b90506117f7602087611c6c565b95506117c6565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b815161183283836115f3565b5061183d838261166a565b50505050565b803560ff8116811461185457600080fd5b919050565b6001600160a01b038116811461186e57600080fd5b50565b6000806040838503121561188457600080fd5b61188d83611843565b9150602083013561189d81611859565b809150509250929050565b6000602082840312156118ba57600080fd5b813561094381611859565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156118fe576118fe6118c5565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561192d5761192d6118c5565b604052919050565b600082601f83011261194657600080fd5b813567ffffffffffffffff811115611960576119606118c5565b611973601f8201601f1916602001611904565b81815284602083860101111561198857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126119b657600080fd5b8135602067ffffffffffffffff808311156119d3576119d36118c5565b8260051b6119e2838201611904565b93845285810183019383810190888611156119fc57600080fd5b84880192505b85831015611a9357823584811115611a1a5760008081fd5b88016040818b03601f1901811315611a325760008081fd5b611a3a6118db565b8783013587811115611a4c5760008081fd5b611a5a8d8a83870101611935565b825250908201359086821115611a705760008081fd5b611a7e8c8984860101611935565b81890152845250509184019190840190611a02565b98975050505050505050565b60008060408385031215611ab257600080fd5b823567ffffffffffffffff811115611ac957600080fd5b611ad5858286016119a5565b95602094909401359450505050565b6000815180845260005b81811015611b0a57602081850181015186830182015201611aee565b506000602082860101526020601f19601f83011685010191505092915050565b604081526000611b3d6040830185611ae4565b905063ffffffff831660208301529392505050565b600060208284031215611b6457600080fd5b61094382611843565b6020815260006109436020830184611ae4565b600060208284031215611b9257600080fd5b813567ffffffffffffffff811115611ba957600080fd5b610aa7848285016119a5565b600181811c90821680611bc957607f821691505b602082108103611be957634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611c2d57611c2d611c05565b5060010190565b604081526000611c476040830185611ae4565b905060ff831660208301529392505050565b8082018082111561094657610946611c05565b8181038181111561094657610946611c05565b634e487b7160e01b600052600160045260246000fd5b604081526000611ca86040830185611ae4565b8281036020840152611cba8185611ae4565b95945050505050565b600081611cd257611cd2611c05565b506000190190565b606081526000611ced6060830186611ae4565b8281036020840152611cff8186611ae4565b90508281036040840152610d688185611ae4565b600060208284031215611d2557600080fd5b8151801515811461094357600080fd5b600082611d5257634e487b7160e01b600052601260045260246000fd5b500690565b808202811582820484141761094657610946611c0556fea2646970667358221220a36fa1213f53338776d2c9565e9a8b3482299a2c13495ac6aaeebf00585273ff64736f6c63430008110033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "constructor": {
        "details": "Constructor.",
        "params": {
          "_anchors": "The binary format RR entries for the root DS records."
        }
      },
      "setAlgorithm(uint8,address)": {
        "details": "Sets the contract address for a signature verification algorithm.      Callable only by the owner.",
        "params": {
          "algo": "The address of the algorithm contract.",
          "id": "The algorithm ID"
        }
      },
      "setDigest(uint8,address)": {
        "details": "Sets the contract address for a digest verification algorithm.      Callable only by the owner.",
        "params": {
          "digest": "The address of the digest contract.",
          "id": "The digest ID"
        }
      },
      "verifyRRSet((bytes,bytes)[])": {
        "details": "Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.      Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.",
        "params": {
          "input": "A list of signed RRSets."
        },
        "returns": {
          "inception": "The inception time of the signed record set.",
          "rrs": "The RRData from the last RRSet in the chain."
        }
      },
      "verifyRRSet((bytes,bytes)[],uint256)": {
        "details": "Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.      Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.",
        "params": {
          "input": "A list of signed RRSets.",
          "now": "The Unix timestamp to validate the records at."
        },
        "returns": {
          "inception": "The inception time of the signed record set.",
          "rrs": "The RRData from the last RRSet in the chain."
        }
      }
    },
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 7153,
        "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
        "label": "anchors",
        "offset": 0,
        "slot": "0",
        "type": "t_bytes_storage"
      },
      {
        "astId": 8130,
        "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
        "label": "owner",
        "offset": 0,
        "slot": "1",
        "type": "t_address"
      },
      {
        "astId": 7285,
        "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
        "label": "algorithms",
        "offset": 0,
        "slot": "2",
        "type": "t_mapping(t_uint8,t_contract(Algorithm)9293)"
      },
      {
        "astId": 7290,
        "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
        "label": "digests",
        "offset": 0,
        "slot": "3",
        "type": "t_mapping(t_uint8,t_contract(Digest)11134)"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_bytes_storage": {
        "encoding": "bytes",
        "label": "bytes",
        "numberOfBytes": "32"
      },
      "t_contract(Algorithm)9293": {
        "encoding": "inplace",
        "label": "contract Algorithm",
        "numberOfBytes": "20"
      },
      "t_contract(Digest)11134": {
        "encoding": "inplace",
        "label": "contract Digest",
        "numberOfBytes": "20"
      },
      "t_mapping(t_uint8,t_contract(Algorithm)9293)": {
        "encoding": "mapping",
        "key": "t_uint8",
        "label": "mapping(uint8 => contract Algorithm)",
        "numberOfBytes": "32",
        "value": "t_contract(Algorithm)9293"
      },
      "t_mapping(t_uint8,t_contract(Digest)11134)": {
        "encoding": "mapping",
        "key": "t_uint8",
        "label": "mapping(uint8 => contract Digest)",
        "numberOfBytes": "32",
        "value": "t_contract(Digest)11134"
      },
      "t_uint8": {
        "encoding": "inplace",
        "label": "uint8",
        "numberOfBytes": "1"
      }
    }
  }
}