VYPR
Low severityNVD Advisory· Published Feb 25, 2026· Updated Feb 25, 2026

ENS DNSSEC Oracle Vulnerable to RSA Signature Forgery via Missing PKCS#1 v1.5 Padding Validation

CVE-2026-22866

Description

Ethereum Name Service (ENS) is a distributed, open, and extensible naming system based on the Ethereum blockchain. In versions 1.6.2 and prior, the RSASHA256Algorithm and RSASHA1Algorithm contracts fail to validate PKCS#1 v1.5 padding structure when verifying RSA signatures. The contracts only check if the last 32 (or 20) bytes of the decrypted signature match the expected hash. This enables Bleichenbacher's 2006 signature forgery attack against DNS zones using RSA keys with low public exponents (e=3). Two ENS-supported TLDs (.cc and .name) use e=3 for their Key Signing Keys, allowing any domain under these TLDs to be fraudulently claimed on ENS without DNS ownership. Apatch was merged at commit c76c5ad0dc9de1c966443bd946fafc6351f87587. Possible workarounds include deploying the patched contracts and pointing DNSSECImpl.setAlgorithm to the deployed contract.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

ENS DNSSEC oracle contracts fail to validate PKCS#1 v1.5 padding, enabling Bleichenbacher's signature forgery for RSA keys with e=3, allowing fraudulent domain claims.

Vulnerability

Overview

The Ethereum Name Service (ENS) DNSSEC oracle contracts RSASHA256Algorithm and RSASHA1Algorithm in versions 1.6.2 and prior contain a critical flaw in their RSA signature verification logic. The contracts only check whether the last 32 bytes (for SHA-256) or 20 bytes (for SHA-1) of the decrypted signature match the expected hash, without validating the PKCS#1 v1.5 padding structure that should precede the hash [1][2]. This omission directly enables Bleichenbacher's 2006 signature forgery attack against RSA signatures with low public exponents, specifically e=3 [2].

Attack

Vector and Exploitation

An attacker can forge a valid DNSSEC signature for any domain under two ENS-supported top-level domains (TLDs) — .cc and .name — because these TLDs use RSA keys with exponent e=3 for their Key Signing Keys (KSKs) [2]. The missing padding validation means the attacker can craft a specially constructed RSA signature that, when decrypted with the public key, produces a result where the final bytes match the expected hash, even though the signature is not genuine. No authentication or prior access is required beyond the ability to submit a DNSSEC proof to the ENS oracle [2].

Impact

Successful exploitation allows an attacker to fraudulently claim any domain under ENS any domain name ending in .cc or .name without actually owning that DNS domain [2]. This undermines the trust model of ENS, which relies on DNSSEC proofs to verify DNS ownership. The attacker could then configure ENS records for the claimed domain, redirect traffic, host malicious content, or impersonate legitimate services under those domains.

Mitigation

A patch has been merged at commit c76c5ad0dc9de1c966443bd946fafc6351f87587 [4]. The fix introduces a new RSAPKCS1Verify library that properly validates the entire PKCS#1 v1.5 structure, including the leading 0x00 0x01 bytes, the padding, and the DigestInfo prefix [4]. As a workaround, deploy the patched contracts and update the DNSSECImpl contract to point to the new algorithm implementations via setAlgorithm [2][3]. The ENS DAO has coordinated a security council multisig to execute the upgrade [3].

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@ensdomains/ens-contractsnpm
<= 1.6.2

Affected products

3

Patches

1
c76c5ad0dc9d

Merge commit from fork

https://github.com/ensdomains/ens-contractsMakoto InoueFeb 25, 2026via ghsa
15 files changed · +540 206
  • contracts/dnssec-oracle/algorithms/RSAPKCS1Verify.sol+86 0 added
    @@ -0,0 +1,86 @@
    +pragma solidity ^0.8.4;
    +
    +import "./RSAVerify.sol";
    +import "../../utils/BytesUtils.sol";
    +
    +/// @dev Library for PKCS#1 v1.5 signature verification
    +library RSAPKCS1Verify {
    +    using BytesUtils for *;
    +
    +    /// @dev PKCS#1 v1.5 DigestInfo prefix for SHA-1
    +    bytes constant SHA1_DIGEST_INFO = hex"3021300906052b0e03021a05000414";
    +
    +    /// @dev PKCS#1 v1.5 DigestInfo prefix for SHA-256
    +    bytes constant SHA256_DIGEST_INFO = hex"3031300d060960864801650304020105000420";
    +
    +    /// @dev Verifies an RSA signature with PKCS#1 v1.5 padding for SHA-1
    +    function verifySHA1(
    +        bytes memory modulus,
    +        bytes memory exponent,
    +        bytes memory sig,
    +        bytes20 hash
    +    ) internal view returns (bool) {
    +        (bool ok, bytes memory result) = recoverAndVerify(modulus, exponent, sig, SHA1_DIGEST_INFO);
    +        return ok && hash == result.readBytes20(result.length - 20);
    +    }
    +
    +    /// @dev Verifies an RSA signature with PKCS#1 v1.5 padding for SHA-256
    +    function verifySHA256(
    +        bytes memory modulus,
    +        bytes memory exponent,
    +        bytes memory sig,
    +        bytes32 hash
    +    ) internal view returns (bool) {
    +        (bool ok, bytes memory result) = recoverAndVerify(modulus, exponent, sig, SHA256_DIGEST_INFO);
    +        return ok && hash == result.readBytes32(result.length - 32);
    +    }
    +
    +    /// @dev Recovers RSA signature and verifies PKCS#1 v1.5 structure
    +    /// Format: 0x00 0x01 [0xFF padding] 0x00 [DigestInfo] [Hash]
    +    /// https://datatracker.ietf.org/doc/html/rfc8017#section-9.2
    +    function recoverAndVerify(
    +        bytes memory modulus,
    +        bytes memory exponent,
    +        bytes memory sig,
    +        bytes memory digestInfo
    +    ) private view returns (bool, bytes memory) {
    +        (bool ok, bytes memory result) = RSAVerify.rsarecover(modulus, exponent, sig);
    +        if (!ok || result.length != modulus.length) {
    +            return (false, result);
    +        }
    +
    +        // Check leading bytes: 0x00 0x01
    +        if (result[0] != 0x00 || result[1] != 0x01) {
    +            return (false, result);
    +        }
    +
    +        // Calculate positions working backwards from the end
    +        uint256 hashLen = digestInfo.length == 15 ? 20 : 32;
    +        uint256 hashStart = result.length - hashLen;
    +        uint256 digestInfoStart = hashStart - digestInfo.length;
    +
    +        // Verify 0x00 separator before DigestInfo
    +        if (result[digestInfoStart - 1] != 0x00) {
    +            return (false, result);
    +        }
    +
    +        // Verify DigestInfo matches expected value
    +        if (!result.equals(digestInfoStart, digestInfo, 0, digestInfo.length)) {
    +            return (false, result);
    +        }
    +
    +        // Verify padding: all bytes from position 2 to separator must be 0xFF
    +        // Minimum 8 bytes of 0xFF padding required (RFC 3447)
    +        uint256 paddingLen = digestInfoStart - 1 - 2;
    +        if (paddingLen < 8) {
    +            return (false, result);
    +        }
    +        for (uint256 i = 2; i < digestInfoStart - 1; i++) {
    +            if (result[i] != 0xFF) {
    +                return (false, result);
    +            }
    +        }
    +
    +        return (true, result);
    +    }
    +}
    
  • contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol+2 8 modified
    @@ -1,7 +1,7 @@
     pragma solidity ^0.8.4;
     
     import "./Algorithm.sol";
    -import "./RSAVerify.sol";
    +import "./RSAPKCS1Verify.sol";
     import "../../utils/BytesUtils.sol";
     import "@ensdomains/solsha1/contracts/SHA1.sol";
     
    @@ -33,12 +33,6 @@ contract RSASHA1Algorithm is Algorithm {
                 );
             }
     
    -        // Recover the message from the signature
    -        bool ok;
    -        bytes memory result;
    -        (ok, result) = RSAVerify.rsarecover(modulus, exponent, sig);
    -
    -        // Verify it ends with the hash of our data
    -        return ok && SHA1.sha1(data) == result.readBytes20(result.length - 20);
    +        return RSAPKCS1Verify.verifySHA1(modulus, exponent, sig, SHA1.sha1(data));
         }
     }
    
  • contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol+2 8 modified
    @@ -1,7 +1,7 @@
     pragma solidity ^0.8.4;
     
     import "./Algorithm.sol";
    -import "./RSAVerify.sol";
    +import "./RSAPKCS1Verify.sol";
     import "../../utils/BytesUtils.sol";
     
     /// @dev Implements the DNSSEC RSASHA256 algorithm.
    @@ -32,12 +32,6 @@ contract RSASHA256Algorithm is Algorithm {
                 );
             }
     
    -        // Recover the message from the signature
    -        bool ok;
    -        bytes memory result;
    -        (ok, result) = RSAVerify.rsarecover(modulus, exponent, sig);
    -
    -        // Verify it ends with the hash of our data
    -        return ok && sha256(data) == result.readBytes32(result.length - 32);
    +        return RSAPKCS1Verify.verifySHA256(modulus, exponent, sig, sha256(data));
         }
     }
    
  • deployments/mainnet/.chain+1 0 added
    @@ -0,0 +1 @@
    +{"chainId":"1","genesisHash":"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}
    \ No newline at end of file
    
  • deployments/mainnet/.chainId+0 1 removed
    @@ -1 +0,0 @@
    -1
    \ No newline at end of file
    
  • deployments/mainnet/P256SHA256Algorithm.json+42 29 modified
    @@ -1,5 +1,5 @@
     {
    -  "address": "0x0faa24e538bA4620165933f68a9d142f79A68091",
    +  "address": "0xb091c4f6fac16edda5ee1e0f4738f80011905878",
       "abi": [
         {
           "inputs": [
    @@ -31,52 +31,65 @@
           "type": "function"
         }
       ],
    -  "transactionHash": "0xb2138ff9bf3e722a0872cf79213cae19374c24976888fe2d55b8d1bf064ae739",
    -  "receipt": {
    -    "to": null,
    -    "from": "0x0904Dac3347eA47d208F3Fd67402D039a3b99859",
    -    "contractAddress": "0x0faa24e538bA4620165933f68a9d142f79A68091",
    -    "transactionIndex": 81,
    -    "gasUsed": "896222",
    -    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    -    "blockHash": "0x71469d1efd1d40280686921cd3585a39755863aa110223c1ce6d51296d409f06",
    -    "transactionHash": "0xb2138ff9bf3e722a0872cf79213cae19374c24976888fe2d55b8d1bf064ae739",
    -    "logs": [],
    -    "blockNumber": 19020683,
    -    "cumulativeGasUsed": "6995824",
    -    "status": 1,
    -    "byzantium": true
    -  },
    -  "args": [],
    -  "numDeployments": 2,
    -  "solcInputHash": "dd9e022689821cffaeb04b9ddbda87ae",
    -  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"verify(bytes,bytes,bytes)\":{\"details\":\"Verifies a signature.\",\"params\":{\"data\":\"The signed data to verify.\",\"key\":\"The public key to verify with.\",\"signature\":\"The signature to verify.\"},\"returns\":{\"_0\":\"True iff the signature is valid.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol\":\"P256SHA256Algorithm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"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/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/algorithms/EllipticCurve.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @title   EllipticCurve\\n *\\n * @author  Tilman Drerup;\\n *\\n * @notice  Implements elliptic curve math; Parametrized for SECP256R1.\\n *\\n *          Includes components of code by Andreas Olofsson, Alexander Vlasov\\n *          (https://github.com/BANKEX/CurveArithmetics), and Avi Asayag\\n *          (https://github.com/orbs-network/elliptic-curve-solidity)\\n *\\n *          Source: https://github.com/tdrerup/elliptic-curve-solidity\\n *\\n * @dev     NOTE: To disambiguate public keys when verifying signatures, activate\\n *          condition 'rs[1] > lowSmax' in validateSignature().\\n */\\ncontract EllipticCurve {\\n    // Set parameters for curve.\\n    uint256 constant a =\\n        0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\\n    uint256 constant b =\\n        0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\\n    uint256 constant gx =\\n        0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\\n    uint256 constant gy =\\n        0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\\n    uint256 constant p =\\n        0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n    uint256 constant n =\\n        0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\\n\\n    uint256 constant lowSmax =\\n        0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0;\\n\\n    /**\\n     * @dev Inverse of u in the field of modulo m.\\n     */\\n    function inverseMod(uint256 u, uint256 m) internal pure returns (uint256) {\\n        unchecked {\\n            if (u == 0 || u == m || m == 0) return 0;\\n            if (u > m) u = u % m;\\n\\n            int256 t1;\\n            int256 t2 = 1;\\n            uint256 r1 = m;\\n            uint256 r2 = u;\\n            uint256 q;\\n\\n            while (r2 != 0) {\\n                q = r1 / r2;\\n                (t1, t2, r1, r2) = (t2, t1 - int256(q) * t2, r2, r1 - q * r2);\\n            }\\n\\n            if (t1 < 0) return (m - uint256(-t1));\\n\\n            return uint256(t1);\\n        }\\n    }\\n\\n    /**\\n     * @dev Transform affine coordinates into projective coordinates.\\n     */\\n    function toProjectivePoint(\\n        uint256 x0,\\n        uint256 y0\\n    ) internal pure returns (uint256[3] memory P) {\\n        P[2] = addmod(0, 1, p);\\n        P[0] = mulmod(x0, P[2], p);\\n        P[1] = mulmod(y0, P[2], p);\\n    }\\n\\n    /**\\n     * @dev Add two points in affine coordinates and return projective point.\\n     */\\n    function addAndReturnProjectivePoint(\\n        uint256 x1,\\n        uint256 y1,\\n        uint256 x2,\\n        uint256 y2\\n    ) internal pure returns (uint256[3] memory P) {\\n        uint256 x;\\n        uint256 y;\\n        (x, y) = add(x1, y1, x2, y2);\\n        P = toProjectivePoint(x, y);\\n    }\\n\\n    /**\\n     * @dev Transform from projective to affine coordinates.\\n     */\\n    function toAffinePoint(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 z0\\n    ) internal pure returns (uint256 x1, uint256 y1) {\\n        uint256 z0Inv;\\n        z0Inv = inverseMod(z0, p);\\n        x1 = mulmod(x0, z0Inv, p);\\n        y1 = mulmod(y0, z0Inv, p);\\n    }\\n\\n    /**\\n     * @dev Return the zero curve in projective coordinates.\\n     */\\n    function zeroProj()\\n        internal\\n        pure\\n        returns (uint256 x, uint256 y, uint256 z)\\n    {\\n        return (0, 1, 0);\\n    }\\n\\n    /**\\n     * @dev Return the zero curve in affine coordinates.\\n     */\\n    function zeroAffine() internal pure returns (uint256 x, uint256 y) {\\n        return (0, 0);\\n    }\\n\\n    /**\\n     * @dev Check if the curve is the zero curve.\\n     */\\n    function isZeroCurve(\\n        uint256 x0,\\n        uint256 y0\\n    ) internal pure returns (bool isZero) {\\n        if (x0 == 0 && y0 == 0) {\\n            return true;\\n        }\\n        return false;\\n    }\\n\\n    /**\\n     * @dev Check if a point in affine coordinates is on the curve.\\n     */\\n    function isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\\n        if (0 == x || x == p || 0 == y || y == p) {\\n            return false;\\n        }\\n\\n        uint256 LHS = mulmod(y, y, p); // y^2\\n        uint256 RHS = mulmod(mulmod(x, x, p), x, p); // x^3\\n\\n        if (a != 0) {\\n            RHS = addmod(RHS, mulmod(x, a, p), p); // x^3 + a*x\\n        }\\n        if (b != 0) {\\n            RHS = addmod(RHS, b, p); // x^3 + a*x + b\\n        }\\n\\n        return LHS == RHS;\\n    }\\n\\n    /**\\n     * @dev Double an elliptic curve point in projective coordinates. See\\n     * https://www.nayuki.io/page/elliptic-curve-point-addition-in-projective-coordinates\\n     */\\n    function twiceProj(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 z0\\n    ) internal pure returns (uint256 x1, uint256 y1, uint256 z1) {\\n        uint256 t;\\n        uint256 u;\\n        uint256 v;\\n        uint256 w;\\n\\n        if (isZeroCurve(x0, y0)) {\\n            return zeroProj();\\n        }\\n\\n        u = mulmod(y0, z0, p);\\n        u = mulmod(u, 2, p);\\n\\n        v = mulmod(u, x0, p);\\n        v = mulmod(v, y0, p);\\n        v = mulmod(v, 2, p);\\n\\n        x0 = mulmod(x0, x0, p);\\n        t = mulmod(x0, 3, p);\\n\\n        z0 = mulmod(z0, z0, p);\\n        z0 = mulmod(z0, a, p);\\n        t = addmod(t, z0, p);\\n\\n        w = mulmod(t, t, p);\\n        x0 = mulmod(2, v, p);\\n        w = addmod(w, p - x0, p);\\n\\n        x0 = addmod(v, p - w, p);\\n        x0 = mulmod(t, x0, p);\\n        y0 = mulmod(y0, u, p);\\n        y0 = mulmod(y0, y0, p);\\n        y0 = mulmod(2, y0, p);\\n        y1 = addmod(x0, p - y0, p);\\n\\n        x1 = mulmod(u, w, p);\\n\\n        z1 = mulmod(u, u, p);\\n        z1 = mulmod(z1, u, p);\\n    }\\n\\n    /**\\n     * @dev Add two elliptic curve points in projective coordinates. See\\n     * https://www.nayuki.io/page/elliptic-curve-point-addition-in-projective-coordinates\\n     */\\n    function addProj(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 z0,\\n        uint256 x1,\\n        uint256 y1,\\n        uint256 z1\\n    ) internal pure returns (uint256 x2, uint256 y2, uint256 z2) {\\n        uint256 t0;\\n        uint256 t1;\\n        uint256 u0;\\n        uint256 u1;\\n\\n        if (isZeroCurve(x0, y0)) {\\n            return (x1, y1, z1);\\n        } else if (isZeroCurve(x1, y1)) {\\n            return (x0, y0, z0);\\n        }\\n\\n        t0 = mulmod(y0, z1, p);\\n        t1 = mulmod(y1, z0, p);\\n\\n        u0 = mulmod(x0, z1, p);\\n        u1 = mulmod(x1, z0, p);\\n\\n        if (u0 == u1) {\\n            if (t0 == t1) {\\n                return twiceProj(x0, y0, z0);\\n            } else {\\n                return zeroProj();\\n            }\\n        }\\n\\n        (x2, y2, z2) = addProj2(mulmod(z0, z1, p), u0, u1, t1, t0);\\n    }\\n\\n    /**\\n     * @dev Helper function that splits addProj to avoid too many local variables.\\n     */\\n    function addProj2(\\n        uint256 v,\\n        uint256 u0,\\n        uint256 u1,\\n        uint256 t1,\\n        uint256 t0\\n    ) private pure returns (uint256 x2, uint256 y2, uint256 z2) {\\n        uint256 u;\\n        uint256 u2;\\n        uint256 u3;\\n        uint256 w;\\n        uint256 t;\\n\\n        t = addmod(t0, p - t1, p);\\n        u = addmod(u0, p - u1, p);\\n        u2 = mulmod(u, u, p);\\n\\n        w = mulmod(t, t, p);\\n        w = mulmod(w, v, p);\\n        u1 = addmod(u1, u0, p);\\n        u1 = mulmod(u1, u2, p);\\n        w = addmod(w, p - u1, p);\\n\\n        x2 = mulmod(u, w, p);\\n\\n        u3 = mulmod(u2, u, p);\\n        u0 = mulmod(u0, u2, p);\\n        u0 = addmod(u0, p - w, p);\\n        t = mulmod(t, u0, p);\\n        t0 = mulmod(t0, u3, p);\\n\\n        y2 = addmod(t, p - t0, p);\\n\\n        z2 = mulmod(u3, v, p);\\n    }\\n\\n    /**\\n     * @dev Add two elliptic curve points in affine coordinates.\\n     */\\n    function add(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 x1,\\n        uint256 y1\\n    ) internal pure returns (uint256, uint256) {\\n        uint256 z0;\\n\\n        (x0, y0, z0) = addProj(x0, y0, 1, x1, y1, 1);\\n\\n        return toAffinePoint(x0, y0, z0);\\n    }\\n\\n    /**\\n     * @dev Double an elliptic curve point in affine coordinates.\\n     */\\n    function twice(\\n        uint256 x0,\\n        uint256 y0\\n    ) internal pure returns (uint256, uint256) {\\n        uint256 z0;\\n\\n        (x0, y0, z0) = twiceProj(x0, y0, 1);\\n\\n        return toAffinePoint(x0, y0, z0);\\n    }\\n\\n    /**\\n     * @dev Multiply an elliptic curve point by a 2 power base (i.e., (2^exp)*P)).\\n     */\\n    function multiplyPowerBase2(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 exp\\n    ) internal pure returns (uint256, uint256) {\\n        uint256 base2X = x0;\\n        uint256 base2Y = y0;\\n        uint256 base2Z = 1;\\n\\n        for (uint256 i = 0; i < exp; i++) {\\n            (base2X, base2Y, base2Z) = twiceProj(base2X, base2Y, base2Z);\\n        }\\n\\n        return toAffinePoint(base2X, base2Y, base2Z);\\n    }\\n\\n    /**\\n     * @dev Multiply an elliptic curve point by a scalar.\\n     */\\n    function multiplyScalar(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 scalar\\n    ) internal pure returns (uint256 x1, uint256 y1) {\\n        if (scalar == 0) {\\n            return zeroAffine();\\n        } else if (scalar == 1) {\\n            return (x0, y0);\\n        } else if (scalar == 2) {\\n            return twice(x0, y0);\\n        }\\n\\n        uint256 base2X = x0;\\n        uint256 base2Y = y0;\\n        uint256 base2Z = 1;\\n        uint256 z1 = 1;\\n        x1 = x0;\\n        y1 = y0;\\n\\n        if (scalar % 2 == 0) {\\n            x1 = y1 = 0;\\n        }\\n\\n        scalar = scalar >> 1;\\n\\n        while (scalar > 0) {\\n            (base2X, base2Y, base2Z) = twiceProj(base2X, base2Y, base2Z);\\n\\n            if (scalar % 2 == 1) {\\n                (x1, y1, z1) = addProj(base2X, base2Y, base2Z, x1, y1, z1);\\n            }\\n\\n            scalar = scalar >> 1;\\n        }\\n\\n        return toAffinePoint(x1, y1, z1);\\n    }\\n\\n    /**\\n     * @dev Multiply the curve's generator point by a scalar.\\n     */\\n    function multipleGeneratorByScalar(\\n        uint256 scalar\\n    ) internal pure returns (uint256, uint256) {\\n        return multiplyScalar(gx, gy, scalar);\\n    }\\n\\n    /**\\n     * @dev Validate combination of message, signature, and public key.\\n     */\\n    function validateSignature(\\n        bytes32 message,\\n        uint256[2] memory rs,\\n        uint256[2] memory Q\\n    ) internal pure returns (bool) {\\n        // To disambiguate between public key solutions, include comment below.\\n        if (rs[0] == 0 || rs[0] >= n || rs[1] == 0) {\\n            // || rs[1] > lowSmax)\\n            return false;\\n        }\\n        if (!isOnCurve(Q[0], Q[1])) {\\n            return false;\\n        }\\n\\n        uint256 x1;\\n        uint256 x2;\\n        uint256 y1;\\n        uint256 y2;\\n\\n        uint256 sInv = inverseMod(rs[1], n);\\n        (x1, y1) = multiplyScalar(gx, gy, mulmod(uint256(message), sInv, n));\\n        (x2, y2) = multiplyScalar(Q[0], Q[1], mulmod(rs[0], sInv, n));\\n        uint256[3] memory P = addAndReturnProjectivePoint(x1, y1, x2, y2);\\n\\n        if (P[2] == 0) {\\n            return false;\\n        }\\n\\n        uint256 Px = inverseMod(P[2], p);\\n        Px = mulmod(P[0], mulmod(Px, Px, p), p);\\n\\n        return Px % n == rs[0];\\n    }\\n}\\n\",\"keccak256\":\"0xdee968ffbfcb9a05b7ed7845e2c55f438f5e09a80fc6024c751a1718137e1838\"},\"contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"./EllipticCurve.sol\\\";\\nimport \\\"../BytesUtils.sol\\\";\\n\\ncontract P256SHA256Algorithm is Algorithm, EllipticCurve {\\n    using BytesUtils for *;\\n\\n    /**\\n     * @dev Verifies a signature.\\n     * @param key The public key to verify with.\\n     * @param data The signed data to verify.\\n     * @param signature The signature to verify.\\n     * @return True iff the signature is valid.\\n     */\\n    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view override returns (bool) {\\n        return\\n            validateSignature(\\n                sha256(data),\\n                parseSignature(signature),\\n                parseKey(key)\\n            );\\n    }\\n\\n    function parseSignature(\\n        bytes memory data\\n    ) internal pure returns (uint256[2] memory) {\\n        require(data.length == 64, \\\"Invalid p256 signature length\\\");\\n        return [uint256(data.readBytes32(0)), uint256(data.readBytes32(32))];\\n    }\\n\\n    function parseKey(\\n        bytes memory data\\n    ) internal pure returns (uint256[2] memory) {\\n        require(data.length == 68, \\\"Invalid p256 key length\\\");\\n        return [uint256(data.readBytes32(4)), uint256(data.readBytes32(36))];\\n    }\\n}\\n\",\"keccak256\":\"0x406e394eb659ee8c75345b9d3795e0061de2bd6567dd8035e76a19588850f0ea\"}},\"version\":1}",
    -  "bytecode": "0x608060405234801561001057600080fd5b50610f41806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610dd4565b610057565b604051901515815260200160405180910390f35b60006101316002868660405161006e929190610e6e565b602060405180830381855afa15801561008b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906100ae9190610e7e565b6100ed85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061013c92505050565b61012c8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101cb92505050565b61024a565b979650505050505050565b610144610d56565b815160401461019a5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c69642070323536207369676e6174757265206c656e67746800000060448201526064015b60405180910390fd5b60408051808201909152806101b0846000610445565b81526020908101906101c3908590610445565b905292915050565b6101d3610d56565b81516044146102245760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642070323536206b6579206c656e6774680000000000000000006044820152606401610191565b604080518082019091528061023a846004610445565b81526020016101c3846024610445565b8151600090158061027c575082517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255111155b8061028957506020830151155b156102965750600061043e565b815160208301516102a79190610469565b6102b35750600061043e565b6000808080806102ea88600160200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551610565565b905061035a7f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f57fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551848d096105ff565b885160208a01518b5193985091955061039a929091907fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551908590096105ff565b909450915060006103ad868587866106cf565b60408101519091506000036103cb576000965050505050505061043e565b60006103ec8260026020020151600160601b63ffffffff60c01b0319610565565b9050600160601b63ffffffff60c01b0319808283098351098a519091506104337fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255183610ead565b149750505050505050505b9392505050565b8151600090610455836020610ee5565b111561046057600080fd5b50016020015190565b60008215806104855750600160601b63ffffffff60c01b031983145b8061048e575081155b806104a65750600160601b63ffffffff60c01b031982145b156104b35750600061055f565b6000600160601b63ffffffff60c01b031983840990506000600160601b63ffffffff60c01b031985600160601b63ffffffff60c01b0319878809099050600160601b63ffffffff60c01b0319807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc870982089050600160601b63ffffffff60c01b03197f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b820890501490505b92915050565b600082158061057357508183145b8061057c575081155b156105895750600061055f565b818311156105a4578183816105a0576105a0610e97565b0692505b600060018385835b81156105db578183816105c1576105c1610e97565b9495940485810290940393919283830290039190506105ac565b60008512156105f357505050908301915061055f9050565b50929695505050505050565b60008082600003610617576000805b915091506106c7565b826001036106295750839050826106c7565b8260020361063b5761060e85856106f5565b50839050828181600180610650600288610ead565b60000361065f57600094508495505b600187901c96505b86156106b357610678848484610725565b9195509350915061068a600288610ead565b6001036106a75761069f848484898986610983565b919750955090505b600187901c9650610667565b6106be868683610a88565b95509550505050505b935093915050565b6106d7610d74565b6000806106e687878787610ad8565b90925090506101318282610b0d565b600080600061070685856001610725565b91965094509050610718858583610a88565b92509250505b9250929050565b600080600080600080600061073a8a8a610b66565b156107535760006001819650965096505050505061097a565b600160601b63ffffffff60c01b0319888a099250600160601b63ffffffff60c01b0319600284099250600160601b63ffffffff60c01b03198a84099150600160601b63ffffffff60c01b03198983099150600160601b63ffffffff60c01b0319600283099150600160601b63ffffffff60c01b03198a8b099950600160601b63ffffffff60c01b031960038b099350600160601b63ffffffff60c01b03198889099750600160601b63ffffffff60c01b03197fffffffff00000001000000000000000000000000fffffffffffffffffffffffc89099750600160601b63ffffffff60c01b03198885089350600160601b63ffffffff60c01b03198485099050600160601b63ffffffff60c01b0319826002099950600160601b63ffffffff60c01b031961088e8b600160601b63ffffffff60c01b0319610ef8565b82089050600160601b63ffffffff60c01b03196108b982600160601b63ffffffff60c01b0319610ef8565b83089950600160601b63ffffffff60c01b03198a85099950600160601b63ffffffff60c01b0319838a099850600160601b63ffffffff60c01b0319898a099850600160601b63ffffffff60c01b0319896002099850600160601b63ffffffff60c01b03196109358a600160601b63ffffffff60c01b0319610ef8565b8b089550600160601b63ffffffff60c01b03198184099650600160601b63ffffffff60c01b03198384099450600160601b63ffffffff60c01b03198386099450505050505b93509350939050565b60008060008060008060006109988d8d610b66565b156109af5789898996509650965050505050610a7c565b6109b98a8a610b66565b156109d0578c8c8c96509650965050505050610a7c565b600160601b63ffffffff60c01b0319888d099350600160601b63ffffffff60c01b03198b8a099250600160601b63ffffffff60c01b0319888e099150600160601b63ffffffff60c01b03198b8b099050808203610a5257828403610a4857610a398d8d8d610725565b96509650965050505050610a7c565b6000600181610a39565b610a70600160601b63ffffffff60c01b0319898d0983838688610b8a565b91985096509450505050505b96509650969350505050565b6000806000610aa584600160601b63ffffffff60c01b0319610565565b9050600160601b63ffffffff60c01b03198187099250600160601b63ffffffff60c01b0319818609915050935093915050565b6000806000610aed8787600188886001610983565b91985096509050610aff878783610a88565b925092505094509492505050565b610b15610d74565b600160601b63ffffffff60c01b0319600160000860408201819052600160601b63ffffffff60c01b031990840981526040810151600160601b63ffffffff60c01b0319908309602082015292915050565b600082158015610b74575081155b15610b815750600161055f565b50600092915050565b600080808080808080600160601b63ffffffff60c01b0319610bba8b600160601b63ffffffff60c01b0319610ef8565b8a089050600160601b63ffffffff60c01b0319610be58c600160601b63ffffffff60c01b0319610ef8565b8d089450600160601b63ffffffff60c01b03198586099350600160601b63ffffffff60c01b03198182099150600160601b63ffffffff60c01b03198d83099150600160601b63ffffffff60c01b03198c8c089a50600160601b63ffffffff60c01b0319848c099a50600160601b63ffffffff60c01b0319610c748c600160601b63ffffffff60c01b0319610ef8565b83089150600160601b63ffffffff60c01b03198286099750600160601b63ffffffff60c01b03198585099250600160601b63ffffffff60c01b0319848d099b50600160601b63ffffffff60c01b0319610cdb83600160601b63ffffffff60c01b0319610ef8565b8d089b50600160601b63ffffffff60c01b03198c82099050600160601b63ffffffff60c01b0319838a099850600160601b63ffffffff60c01b0319610d2e8a600160601b63ffffffff60c01b0319610ef8565b82089650600160601b63ffffffff60c01b03198d840995505050505050955095509592505050565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60008083601f840112610da457600080fd5b50813567ffffffffffffffff811115610dbc57600080fd5b60208301915083602082850101111561071e57600080fd5b60008060008060008060608789031215610ded57600080fd5b863567ffffffffffffffff80821115610e0557600080fd5b610e118a838b01610d92565b90985096506020890135915080821115610e2a57600080fd5b610e368a838b01610d92565b90965094506040890135915080821115610e4f57600080fd5b50610e5c89828a01610d92565b979a9699509497509295939492505050565b8183823760009101908152919050565b600060208284031215610e9057600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b600082610eca57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b8082018082111561055f5761055f610ecf565b8181038181111561055f5761055f610ecf56fea26469706673582212200a7cdc61343825b33e51ff653c60245b511afc3bf209bfd7831b5eded2744b1c64736f6c63430008110033",
    -  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610dd4565b610057565b604051901515815260200160405180910390f35b60006101316002868660405161006e929190610e6e565b602060405180830381855afa15801561008b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906100ae9190610e7e565b6100ed85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061013c92505050565b61012c8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101cb92505050565b61024a565b979650505050505050565b610144610d56565b815160401461019a5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c69642070323536207369676e6174757265206c656e67746800000060448201526064015b60405180910390fd5b60408051808201909152806101b0846000610445565b81526020908101906101c3908590610445565b905292915050565b6101d3610d56565b81516044146102245760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642070323536206b6579206c656e6774680000000000000000006044820152606401610191565b604080518082019091528061023a846004610445565b81526020016101c3846024610445565b8151600090158061027c575082517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255111155b8061028957506020830151155b156102965750600061043e565b815160208301516102a79190610469565b6102b35750600061043e565b6000808080806102ea88600160200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551610565565b905061035a7f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f57fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551848d096105ff565b885160208a01518b5193985091955061039a929091907fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551908590096105ff565b909450915060006103ad868587866106cf565b60408101519091506000036103cb576000965050505050505061043e565b60006103ec8260026020020151600160601b63ffffffff60c01b0319610565565b9050600160601b63ffffffff60c01b0319808283098351098a519091506104337fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255183610ead565b149750505050505050505b9392505050565b8151600090610455836020610ee5565b111561046057600080fd5b50016020015190565b60008215806104855750600160601b63ffffffff60c01b031983145b8061048e575081155b806104a65750600160601b63ffffffff60c01b031982145b156104b35750600061055f565b6000600160601b63ffffffff60c01b031983840990506000600160601b63ffffffff60c01b031985600160601b63ffffffff60c01b0319878809099050600160601b63ffffffff60c01b0319807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc870982089050600160601b63ffffffff60c01b03197f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b820890501490505b92915050565b600082158061057357508183145b8061057c575081155b156105895750600061055f565b818311156105a4578183816105a0576105a0610e97565b0692505b600060018385835b81156105db578183816105c1576105c1610e97565b9495940485810290940393919283830290039190506105ac565b60008512156105f357505050908301915061055f9050565b50929695505050505050565b60008082600003610617576000805b915091506106c7565b826001036106295750839050826106c7565b8260020361063b5761060e85856106f5565b50839050828181600180610650600288610ead565b60000361065f57600094508495505b600187901c96505b86156106b357610678848484610725565b9195509350915061068a600288610ead565b6001036106a75761069f848484898986610983565b919750955090505b600187901c9650610667565b6106be868683610a88565b95509550505050505b935093915050565b6106d7610d74565b6000806106e687878787610ad8565b90925090506101318282610b0d565b600080600061070685856001610725565b91965094509050610718858583610a88565b92509250505b9250929050565b600080600080600080600061073a8a8a610b66565b156107535760006001819650965096505050505061097a565b600160601b63ffffffff60c01b0319888a099250600160601b63ffffffff60c01b0319600284099250600160601b63ffffffff60c01b03198a84099150600160601b63ffffffff60c01b03198983099150600160601b63ffffffff60c01b0319600283099150600160601b63ffffffff60c01b03198a8b099950600160601b63ffffffff60c01b031960038b099350600160601b63ffffffff60c01b03198889099750600160601b63ffffffff60c01b03197fffffffff00000001000000000000000000000000fffffffffffffffffffffffc89099750600160601b63ffffffff60c01b03198885089350600160601b63ffffffff60c01b03198485099050600160601b63ffffffff60c01b0319826002099950600160601b63ffffffff60c01b031961088e8b600160601b63ffffffff60c01b0319610ef8565b82089050600160601b63ffffffff60c01b03196108b982600160601b63ffffffff60c01b0319610ef8565b83089950600160601b63ffffffff60c01b03198a85099950600160601b63ffffffff60c01b0319838a099850600160601b63ffffffff60c01b0319898a099850600160601b63ffffffff60c01b0319896002099850600160601b63ffffffff60c01b03196109358a600160601b63ffffffff60c01b0319610ef8565b8b089550600160601b63ffffffff60c01b03198184099650600160601b63ffffffff60c01b03198384099450600160601b63ffffffff60c01b03198386099450505050505b93509350939050565b60008060008060008060006109988d8d610b66565b156109af5789898996509650965050505050610a7c565b6109b98a8a610b66565b156109d0578c8c8c96509650965050505050610a7c565b600160601b63ffffffff60c01b0319888d099350600160601b63ffffffff60c01b03198b8a099250600160601b63ffffffff60c01b0319888e099150600160601b63ffffffff60c01b03198b8b099050808203610a5257828403610a4857610a398d8d8d610725565b96509650965050505050610a7c565b6000600181610a39565b610a70600160601b63ffffffff60c01b0319898d0983838688610b8a565b91985096509450505050505b96509650969350505050565b6000806000610aa584600160601b63ffffffff60c01b0319610565565b9050600160601b63ffffffff60c01b03198187099250600160601b63ffffffff60c01b0319818609915050935093915050565b6000806000610aed8787600188886001610983565b91985096509050610aff878783610a88565b925092505094509492505050565b610b15610d74565b600160601b63ffffffff60c01b0319600160000860408201819052600160601b63ffffffff60c01b031990840981526040810151600160601b63ffffffff60c01b0319908309602082015292915050565b600082158015610b74575081155b15610b815750600161055f565b50600092915050565b600080808080808080600160601b63ffffffff60c01b0319610bba8b600160601b63ffffffff60c01b0319610ef8565b8a089050600160601b63ffffffff60c01b0319610be58c600160601b63ffffffff60c01b0319610ef8565b8d089450600160601b63ffffffff60c01b03198586099350600160601b63ffffffff60c01b03198182099150600160601b63ffffffff60c01b03198d83099150600160601b63ffffffff60c01b03198c8c089a50600160601b63ffffffff60c01b0319848c099a50600160601b63ffffffff60c01b0319610c748c600160601b63ffffffff60c01b0319610ef8565b83089150600160601b63ffffffff60c01b03198286099750600160601b63ffffffff60c01b03198585099250600160601b63ffffffff60c01b0319848d099b50600160601b63ffffffff60c01b0319610cdb83600160601b63ffffffff60c01b0319610ef8565b8d089b50600160601b63ffffffff60c01b03198c82099050600160601b63ffffffff60c01b0319838a099850600160601b63ffffffff60c01b0319610d2e8a600160601b63ffffffff60c01b0319610ef8565b82089650600160601b63ffffffff60c01b03198d840995505050505050955095509592505050565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60008083601f840112610da457600080fd5b50813567ffffffffffffffff811115610dbc57600080fd5b60208301915083602082850101111561071e57600080fd5b60008060008060008060608789031215610ded57600080fd5b863567ffffffffffffffff80821115610e0557600080fd5b610e118a838b01610d92565b90985096506020890135915080821115610e2a57600080fd5b610e368a838b01610d92565b90965094506040890135915080821115610e4f57600080fd5b50610e5c89828a01610d92565b979a9699509497509295939492505050565b8183823760009101908152919050565b600060208284031215610e9057600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b600082610eca57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b8082018082111561055f5761055f610ecf565b8181038181111561055f5761055f610ecf56fea26469706673582212200a7cdc61343825b33e51ff653c60245b511afc3bf209bfd7831b5eded2744b1c64736f6c63430008110033",
    +  "contractName": "P256SHA256Algorithm",
    +  "sourceName": "contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol",
    +  "bytecode": "0x6080604052348015600f57600080fd5b5061040f8061001f6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046102db565b610057565b604051901515815260200160405180910390f35b6000604082146100c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c69642070323536207369676e6174757265206c656e67746800000060448201526064015b60405180910390fd5b60448614610132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c69642070323536206b6579206c656e67746800000000000000000060448201526064016100bf565b60405183359060208501359060048a01359060248b0135906101a79060029061015e908c908c90610381565b602060405180830381855afa15801561017b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061019e9190610391565b858585856101b6565b9b9a5050505050505050505050565b604080516020808201889052818301879052606082018690526080820185905260a08083018590528351808403909101815260c083018281526101008401909452600093909284929060e001818036833701905050905060208082018351602085016101005afa925082156102875780517f0100000000000000000000000000000000000000000000000000000000000000908290601f90811061025c5761025c6103aa565b01602001517fff00000000000000000000000000000000000000000000000000000000000000161492505b505095945050505050565b60008083601f8401126102a457600080fd5b50813567ffffffffffffffff8111156102bc57600080fd5b6020830191508360208285010111156102d457600080fd5b9250929050565b600080600080600080606087890312156102f457600080fd5b863567ffffffffffffffff81111561030b57600080fd5b61031789828a01610292565b909750955050602087013567ffffffffffffffff81111561033757600080fd5b61034389828a01610292565b909550935050604087013567ffffffffffffffff81111561036357600080fd5b61036f89828a01610292565b979a9699509497509295939492505050565b8183823760009101908152919050565b6000602082840312156103a357600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea26469706673582212206a9a1972102f1fd2de37e61dcce15b6329edc418622ab7ccd8ac51852a1c48b864736f6c634300081a0033",
    +  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046102db565b610057565b604051901515815260200160405180910390f35b6000604082146100c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c69642070323536207369676e6174757265206c656e67746800000060448201526064015b60405180910390fd5b60448614610132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c69642070323536206b6579206c656e67746800000000000000000060448201526064016100bf565b60405183359060208501359060048a01359060248b0135906101a79060029061015e908c908c90610381565b602060405180830381855afa15801561017b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061019e9190610391565b858585856101b6565b9b9a5050505050505050505050565b604080516020808201889052818301879052606082018690526080820185905260a08083018590528351808403909101815260c083018281526101008401909452600093909284929060e001818036833701905050905060208082018351602085016101005afa925082156102875780517f0100000000000000000000000000000000000000000000000000000000000000908290601f90811061025c5761025c6103aa565b01602001517fff00000000000000000000000000000000000000000000000000000000000000161492505b505095945050505050565b60008083601f8401126102a457600080fd5b50813567ffffffffffffffff8111156102bc57600080fd5b6020830191508360208285010111156102d457600080fd5b9250929050565b600080600080600080606087890312156102f457600080fd5b863567ffffffffffffffff81111561030b57600080fd5b61031789828a01610292565b909750955050602087013567ffffffffffffffff81111561033757600080fd5b61034389828a01610292565b909550935050604087013567ffffffffffffffff81111561036357600080fd5b61036f89828a01610292565b979a9699509497509295939492505050565b8183823760009101908152919050565b6000602082840312156103a357600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea26469706673582212206a9a1972102f1fd2de37e61dcce15b6329edc418622ab7ccd8ac51852a1c48b864736f6c634300081a0033",
    +  "linkReferences": {},
    +  "deployedLinkReferences": {},
    +  "immutableReferences": {},
    +  "inputSourceName": "project/contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol",
       "devdoc": {
    +    "details": "Replaces the Solidity-based EllipticCurve implementation with native P-256 verification",
         "kind": "dev",
         "methods": {
           "verify(bytes,bytes,bytes)": {
    -        "details": "Verifies a signature.",
    +        "details": "Verifies a DNSSEC signature.",
             "params": {
               "data": "The signed data to verify.",
    -          "key": "The public key to verify with.",
    -          "signature": "The signature to verify."
    +          "key": "The DNSKEY RDATA (68 bytes: 4-byte header + 64-byte public key).",
    +          "signature": "The signature to verify (64 bytes: r + s)."
             },
             "returns": {
               "_0": "True iff the signature is valid."
             }
           }
         },
    +    "title": "P256SHA256Algorithm",
         "version": 1
       },
    +  "evm": {
    +    "gasEstimates": {
    +      "creation": {
    +        "codeDepositCost": "207800",
    +        "executionCost": "251",
    +        "totalCost": "208051"
    +      },
    +      "external": {
    +        "verify(bytes,bytes,bytes)": "infinite"
    +      }
    +    }
    +  },
    +  "metadata": "{\"compiler\":{\"version\":\"0.8.26+commit.8a97fa7a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Replaces the Solidity-based EllipticCurve implementation with native P-256 verification\",\"kind\":\"dev\",\"methods\":{\"verify(bytes,bytes,bytes)\":{\"details\":\"Verifies a DNSSEC signature.\",\"params\":{\"data\":\"The signed data to verify.\",\"key\":\"The DNSKEY RDATA (68 bytes: 4-byte header + 64-byte public key).\",\"signature\":\"The signature to verify (64 bytes: r + s).\"},\"returns\":{\"_0\":\"True iff the signature is valid.\"}}},\"title\":\"P256SHA256Algorithm\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"DNSSEC Algorithm 13 (ECDSAP256SHA256) implementation using EIP-7951 precompile\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol\":\"P256SHA256Algorithm\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[\"project/:@ensdomains/solsha1/=npm/@ensdomains/solsha1@0.0.3/\"]},\"sources\":{\"project/contracts/dnssec-oracle/algorithms/Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/// @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\\ninterface Algorithm {\\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    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xbcbdc06d72b64903e733e7ddfbf59c35c984c3eb0022baacab12c97292cc13df\"},\"project/contracts/dnssec-oracle/algorithms/P256Precompile.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary P256Precompile {\\n    /// @dev Verifies a P-256 ECDSA signature using EIP-7951 precompile.\\n    /// @param messageHash The SHA-256 hash of the message being verified.\\n    /// @param r The r component of the signature (32 bytes).\\n    /// @param s The s component of the signature (32 bytes).\\n    /// @param qx The x-coordinate of the public key (32 bytes).\\n    /// @param qy The y-coordinate of the public key (32 bytes).\\n    /// @return success True if the signature is valid, false otherwise.\\n    function verify(\\n        bytes32 messageHash,\\n        bytes32 r,\\n        bytes32 s,\\n        bytes32 qx,\\n        bytes32 qy\\n    ) internal view returns (bool success) {\\n        // EIP-7951 precompile input: hash(32) + r(32) + s(32) + x(32) + y(32) = 160 bytes\\n        bytes memory input = abi.encodePacked(messageHash, r, s, qx, qy);\\n\\n        bytes memory output = new bytes(32);\\n\\n        assembly {\\n            success := staticcall(\\n                gas(),\\n                0x100, // EIP-7951 P-256 precompile address\\n                add(input, 32),\\n                mload(input), // 160 bytes\\n                add(output, 32),\\n                32 // Output is 32 bytes\\n            )\\n        }\\n\\n        // Precompile returns 32 bytes: 0x00...01 for valid, 0x00...00 for invalid\\n        if (success) {\\n            success = (output[31] == bytes1(0x01));\\n        }\\n    }\\n}\\n\\n\",\"keccak256\":\"0x88601b4d6eca961bade47e553477b634a7652827ecb00c488f020c1c86bfccb1\"},\"project/contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"./P256Precompile.sol\\\";\\n\\n/// @title P256SHA256Algorithm\\n/// @notice DNSSEC Algorithm 13 (ECDSAP256SHA256) implementation using EIP-7951 precompile\\n/// @dev Replaces the Solidity-based EllipticCurve implementation with native P-256 verification\\ncontract P256SHA256Algorithm is Algorithm {\\n    /// @dev Verifies a DNSSEC signature.\\n    /// @param key The DNSKEY RDATA (68 bytes: 4-byte header + 64-byte public key).\\n    /// @param data The signed data to verify.\\n    /// @param signature The signature to verify (64 bytes: r + s).\\n    /// @return True iff the signature is valid.\\n    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view override returns (bool) {\\n        require(signature.length == 64, \\\"Invalid p256 signature length\\\");\\n        require(key.length == 68, \\\"Invalid p256 key length\\\");\\n\\n        // Extract signature components (r, s) and public key (qx, qy)\\n        // Key format: 4-byte DNSKEY header (flags, protocol, algorithm) + 64-byte public key\\n        bytes32 r;\\n        bytes32 s;\\n        bytes32 qx;\\n        bytes32 qy;\\n\\n        assembly {\\n            // signature.offset points to start of signature in calldata\\n            r := calldataload(signature.offset)\\n            s := calldataload(add(signature.offset, 32))\\n            // key.offset + 4 skips the DNSKEY header\\n            qx := calldataload(add(key.offset, 4))\\n            qy := calldataload(add(key.offset, 36))\\n        }\\n\\n        return P256Precompile.verify(sha256(data), r, s, qx, qy);\\n    }\\n}\\n\",\"keccak256\":\"0xd204330d635252f9e87d35920d1934c160a45007482916c207fc9dc51549dc81\",\"license\":\"MIT\"}},\"version\":1}",
    +  "storageLayout": {
    +    "storage": [],
    +    "types": null
    +  },
       "userdoc": {
         "kind": "user",
         "methods": {},
    +    "notice": "DNSSEC Algorithm 13 (ECDSAP256SHA256) implementation using EIP-7951 precompile",
         "version": 1
       },
    -  "storageLayout": {
    -    "storage": [],
    -    "types": null
    +  "argsData": "0x",
    +  "transaction": {
    +    "hash": "0x8f6ed545325f825ebaa4979959ffae821c8f802711e8a0c214d83037e2d04180",
    +    "nonce": "0x2",
    +    "origin": "0x4e472d50f3d735e76a143afcadae7f03db6995de"
    +  },
    +  "receipt": {
    +    "blockHash": "0x463c1f0d969c7724d90ff50f5d50047430ab614c925371b403e20fba371c3f1c",
    +    "blockNumber": "0x1763f19",
    +    "transactionIndex": "0x10"
       }
     }
    \ No newline at end of file
    
  • deployments/mainnet/RSASHA1Algorithm.json+59 26 modified
    @@ -1,6 +1,22 @@
     {
    -  "address": "0x6ca8624Bc207F043D140125486De0f7E624e37A1",
    +  "address": "0x58e0383e21f25dab957f6664240445a514e9f5e8",
       "abi": [
    +    {
    +      "inputs": [
    +        {
    +          "internalType": "uint256",
    +          "name": "offset",
    +          "type": "uint256"
    +        },
    +        {
    +          "internalType": "uint256",
    +          "name": "length",
    +          "type": "uint256"
    +        }
    +      ],
    +      "name": "OffsetOutOfBoundsError",
    +      "type": "error"
    +    },
         {
           "inputs": [
             {
    @@ -31,41 +47,58 @@
           "type": "function"
         }
       ],
    -  "transactionHash": "0xb7c94bd5d50e457e72c2880a671a61d5a834edb9d10fcbc5225b4094a09ebae4",
    -  "receipt": {
    -    "to": null,
    -    "from": "0x0904Dac3347eA47d208F3Fd67402D039a3b99859",
    -    "contractAddress": "0x6ca8624Bc207F043D140125486De0f7E624e37A1",
    -    "transactionIndex": 99,
    -    "gasUsed": "695194",
    -    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    -    "blockHash": "0x2cfbe854ef4921cee8511fa586d4c14a5cee499656c89c20e5519a44e0ebc23f",
    -    "transactionHash": "0xb7c94bd5d50e457e72c2880a671a61d5a834edb9d10fcbc5225b4094a09ebae4",
    -    "logs": [],
    -    "blockNumber": 19020681,
    -    "cumulativeGasUsed": "7769977",
    -    "status": 1,
    -    "byzantium": true
    -  },
    -  "args": [],
    -  "numDeployments": 2,
    -  "solcInputHash": "dd9e022689821cffaeb04b9ddbda87ae",
    -  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements the DNSSEC RSASHA1 algorithm.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol\":\"RSASHA1Algorithm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"@ensdomains/solsha1/contracts/SHA1.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary SHA1 {\\n    event Debug(bytes32 x);\\n\\n    function sha1(bytes memory data) internal pure returns(bytes20 ret) {\\n        assembly {\\n            // Get a safe scratch location\\n            let scratch := mload(0x40)\\n\\n            // Get the data length, and point data at the first byte\\n            let len := mload(data)\\n            data := add(data, 32)\\n\\n            // Find the length after padding\\n            let totallen := add(and(add(len, 1), 0xFFFFFFFFFFFFFFC0), 64)\\n            switch lt(sub(totallen, len), 9)\\n            case 1 { totallen := add(totallen, 64) }\\n\\n            let h := 0x6745230100EFCDAB890098BADCFE001032547600C3D2E1F0\\n\\n            function readword(ptr, off, count) -> result {\\n                result := 0\\n                if lt(off, count) {\\n                    result := mload(add(ptr, off))\\n                    count := sub(count, off)\\n                    if lt(count, 32) {\\n                        let mask := not(sub(exp(256, sub(32, count)), 1))\\n                        result := and(result, mask)\\n                    }\\n                }\\n            }\\n\\n            for { let i := 0 } lt(i, totallen) { i := add(i, 64) } {\\n                mstore(scratch, readword(data, i, len))\\n                mstore(add(scratch, 32), readword(data, add(i, 32), len))\\n\\n                // If we loaded the last byte, store the terminator byte\\n                switch lt(sub(len, i), 64)\\n                case 1 { mstore8(add(scratch, sub(len, i)), 0x80) }\\n\\n                // If this is the last block, store the length\\n                switch eq(i, sub(totallen, 64))\\n                case 1 { mstore(add(scratch, 32), or(mload(add(scratch, 32)), mul(len, 8))) }\\n\\n                // Expand the 16 32-bit words into 80\\n                for { let j := 64 } lt(j, 128) { j := add(j, 12) } {\\n                    let temp := xor(xor(mload(add(scratch, sub(j, 12))), mload(add(scratch, sub(j, 32)))), xor(mload(add(scratch, sub(j, 56))), mload(add(scratch, sub(j, 64)))))\\n                    temp := or(and(mul(temp, 2), 0xFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE), and(div(temp, 0x80000000), 0x0000000100000001000000010000000100000001000000010000000100000001))\\n                    mstore(add(scratch, j), temp)\\n                }\\n                for { let j := 128 } lt(j, 320) { j := add(j, 24) } {\\n                    let temp := xor(xor(mload(add(scratch, sub(j, 24))), mload(add(scratch, sub(j, 64)))), xor(mload(add(scratch, sub(j, 112))), mload(add(scratch, sub(j, 128)))))\\n                    temp := or(and(mul(temp, 4), 0xFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFC), and(div(temp, 0x40000000), 0x0000000300000003000000030000000300000003000000030000000300000003))\\n                    mstore(add(scratch, j), temp)\\n                }\\n\\n                let x := h\\n                let f := 0\\n                let k := 0\\n                for { let j := 0 } lt(j, 80) { j := add(j, 1) } {\\n                    switch div(j, 20)\\n                    case 0 {\\n                        // f = d xor (b and (c xor d))\\n                        f := xor(div(x, 0x100000000000000000000), div(x, 0x10000000000))\\n                        f := and(div(x, 0x1000000000000000000000000000000), f)\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0x5A827999\\n                    }\\n                    case 1{\\n                        // f = b xor c xor d\\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0x6ED9EBA1\\n                    }\\n                    case 2 {\\n                        // f = (b and c) or (d and (b or c))\\n                        f := or(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := and(div(x, 0x10000000000), f)\\n                        f := or(and(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000)), f)\\n                        k := 0x8F1BBCDC\\n                    }\\n                    case 3 {\\n                        // f = b xor c xor d\\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0xCA62C1D6\\n                    }\\n                    // temp = (a leftrotate 5) + f + e + k + w[i]\\n                    let temp := and(div(x, 0x80000000000000000000000000000000000000000000000), 0x1F)\\n                    temp := or(and(div(x, 0x800000000000000000000000000000000000000), 0xFFFFFFE0), temp)\\n                    temp := add(f, temp)\\n                    temp := add(and(x, 0xFFFFFFFF), temp)\\n                    temp := add(k, temp)\\n                    temp := add(div(mload(add(scratch, mul(j, 4))), 0x100000000000000000000000000000000000000000000000000000000), temp)\\n                    x := or(div(x, 0x10000000000), mul(temp, 0x10000000000000000000000000000000000000000))\\n                    x := or(and(x, 0xFFFFFFFF00FFFFFFFF000000000000FFFFFFFF00FFFFFFFF), mul(or(and(div(x, 0x4000000000000), 0xC0000000), and(div(x, 0x400000000000000000000), 0x3FFFFFFF)), 0x100000000000000000000))\\n                }\\n\\n                h := and(add(h, x), 0xFFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF)\\n            }\\n            ret := mul(or(or(or(or(and(div(h, 0x100000000), 0xFFFFFFFF00000000000000000000000000000000), and(div(h, 0x1000000), 0xFFFFFFFF000000000000000000000000)), and(div(h, 0x10000), 0xFFFFFFFF0000000000000000)), and(div(h, 0x100), 0xFFFFFFFF00000000)), and(h, 0xFFFFFFFF)), 0x1000000000000000000000000)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x746d9b85de197afbc13182cbe4ba4f7917f19594e07c655d6a0c85fdf7460a8a\"},\"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/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/algorithms/ModexpPrecompile.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary ModexpPrecompile {\\n    /**\\n     * @dev Computes (base ^ exponent) % modulus over big numbers.\\n     */\\n    function modexp(\\n        bytes memory base,\\n        bytes memory exponent,\\n        bytes memory modulus\\n    ) internal view returns (bool success, bytes memory output) {\\n        bytes memory input = abi.encodePacked(\\n            uint256(base.length),\\n            uint256(exponent.length),\\n            uint256(modulus.length),\\n            base,\\n            exponent,\\n            modulus\\n        );\\n\\n        output = new bytes(modulus.length);\\n\\n        assembly {\\n            success := staticcall(\\n                gas(),\\n                5,\\n                add(input, 32),\\n                mload(input),\\n                add(output, 32),\\n                mload(modulus)\\n            )\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xb3d46284534eb99061d4c79968c2d0420b63a6649d118ef2ea3608396b85de3f\"},\"contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"../BytesUtils.sol\\\";\\nimport \\\"./RSAVerify.sol\\\";\\nimport \\\"@ensdomains/solsha1/contracts/SHA1.sol\\\";\\n\\n/**\\n * @dev Implements the DNSSEC RSASHA1 algorithm.\\n */\\ncontract RSASHA1Algorithm is Algorithm {\\n    using BytesUtils for *;\\n\\n    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata sig\\n    ) external view override returns (bool) {\\n        bytes memory exponent;\\n        bytes memory modulus;\\n\\n        uint16 exponentLen = uint16(key.readUint8(4));\\n        if (exponentLen != 0) {\\n            exponent = key.substring(5, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 5,\\n                key.length - exponentLen - 5\\n            );\\n        } else {\\n            exponentLen = key.readUint16(5);\\n            exponent = key.substring(7, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 7,\\n                key.length - exponentLen - 7\\n            );\\n        }\\n\\n        // Recover the message from the signature\\n        bool ok;\\n        bytes memory result;\\n        (ok, result) = RSAVerify.rsarecover(modulus, exponent, sig);\\n\\n        // Verify it ends with the hash of our data\\n        return ok && SHA1.sha1(data) == result.readBytes20(result.length - 20);\\n    }\\n}\\n\",\"keccak256\":\"0x5dee71f5a212ef48761ab4154fd68fb738eaefe145ee6c3a30d0ed6c63782b55\"},\"contracts/dnssec-oracle/algorithms/RSAVerify.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"../BytesUtils.sol\\\";\\nimport \\\"./ModexpPrecompile.sol\\\";\\n\\nlibrary RSAVerify {\\n    /**\\n     * @dev Recovers the input data from an RSA signature, returning the result in S.\\n     * @param N The RSA public modulus.\\n     * @param E The RSA public exponent.\\n     * @param S The signature to recover.\\n     * @return True if the recovery succeeded.\\n     */\\n    function rsarecover(\\n        bytes memory N,\\n        bytes memory E,\\n        bytes memory S\\n    ) internal view returns (bool, bytes memory) {\\n        return ModexpPrecompile.modexp(S, E, N);\\n    }\\n}\\n\",\"keccak256\":\"0xb386daa80070f79399a2cb97a534f31660161ccd50662fabcf63e26cce064506\"}},\"version\":1}",
    -  "bytecode": "0x608060405234801561001057600080fd5b50610bac806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046109e6565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103009050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b9250610167610107826005610a96565b61ffff9081169060059061011d9085168d610ab8565b6101279190610ab8565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b9150610227565b6101b260058b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103a99050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b925061022461020e826007610a96565b61ffff9081169060079061011d9085168d610ab8565b91505b6000606061026c84868a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103d192505050565b90925090508180156102f057506102916014825161028a9190610ab8565b82906103ec565b6bffffffffffffffffffffffff19166102df8b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061041f92505050565b6bffffffffffffffffffffffff1916145b9c9b505050505050505050505050565b600082828151811061031457610314610acb565b016020015160f81c90505b92915050565b82516060906103348385610ae1565b111561033f57600080fd5b60008267ffffffffffffffff81111561035a5761035a610af4565b6040519080825280601f01601f191660200182016040528015610384576020820181803683370190505b5090506020808201908686010161039c8282876108b0565b50909150505b9392505050565b81516000906103b9836002610ae1565b11156103c457600080fd5b50016002015161ffff1690565b600060606103e0838587610906565b91509150935093915050565b81516000906103fc836014610ae1565b111561040757600080fd5b5001602001516bffffffffffffffffffffffff191690565b60006040518251602084019350604067ffffffffffffffc060018301160160098282031060018103610452576040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f06104a4565b6000838310156103a2575080820151928290039260208410156103a25760001960208590036101000a0119169392505050565b60005b82811015610830576104ba848289610471565b85526104ca846020830189610471565b6020860152604081850310600181036104e65760808286038701535b506040830381146001810361050357602086018051600887021790525b5060405b608081101561058b57858101603f19810151603719820151601f19830151600b198401516002911891909218189081027ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe1663800000009091047c010000000100000001000000010000000100000001000000010000000116179052600c01610507565b5060805b61014081101561061457858101607f19810151606f19820151603f198301516017198401516004911891909218189081027ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc1663400000009091047c03000000030000000300000003000000030000000300000003000000031617905260180161058f565b508160008060005b60508110156108065760148104801561064c576001811461067c57600281146106aa57600381146106dd57610707565b6501000000000085046a010000000000000000000086048118600160781b870416189350635a8279999250610707565b650100000000008504600160781b86046a0100000000000000000000870418189350636ed9eba19250610707565b6a01000000000000000000008504600160781b8604818117650100000000008804169116179350638f1bbcdc9250610707565b650100000000008504600160781b86046a010000000000000000000087041818935063ca62c1d692505b50601f770800000000000000000000000000000000000000000000008504168063ffffffe073080000000000000000000000000000000000000087041617905080840190508063ffffffff86160190508083019050807c0100000000000000000000000000000000000000000000000000000000600484028c015104019050740100000000000000000000000000000000000000008102650100000000008604179450506a0100000000000000000000633fffffff6a040000000000000000000086041663c00000006604000000000000870416170277ffffffff00ffffffff000000000000ffffffff00ffffffff851617935060018101905061061c565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff16906040016104a7565b506c0100000000000000000000000063ffffffff821667ffffffff000000006101008404166bffffffff0000000000000000620100008504166fffffffff000000000000000000000000630100000086041673ffffffff000000000000000000000000000000006401000000008704161717171702945050505050919050565b602081106108e857815183526108c7602084610ae1565b92506108d4602083610ae1565b91506108e1602082610ab8565b90506108b0565b905182516020929092036101000a6000190180199091169116179052565b60006060600085518551855188888860405160200161092a96959493929190610b3a565b6040516020818303038152906040529050835167ffffffffffffffff81111561095557610955610af4565b6040519080825280601f01601f19166020018201604052801561097f576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b60008083601f8401126109af57600080fd5b50813567ffffffffffffffff8111156109c757600080fd5b6020830191508360208285010111156109df57600080fd5b9250929050565b600080600080600080606087890312156109ff57600080fd5b863567ffffffffffffffff80821115610a1757600080fd5b610a238a838b0161099d565b90985096506020890135915080821115610a3c57600080fd5b610a488a838b0161099d565b90965094506040890135915080821115610a6157600080fd5b50610a6e89828a0161099d565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b61ffff818116838216019080821115610ab157610ab1610a80565b5092915050565b8181038181111561031f5761031f610a80565b634e487b7160e01b600052603260045260246000fd5b8082018082111561031f5761031f610a80565b634e487b7160e01b600052604160045260246000fd5b6000815160005b81811015610b2b5760208185018101518683015201610b11565b50600093019283525090919050565b8681528560208201528460408201526000610b6a610b64610b5e6060850188610b0a565b86610b0a565b84610b0a565b9897505050505050505056fea26469706673582212207857b7c8a67e5fd64e3ccb8e7b2e6fbd8ac879a5659d7498b1bc12aeeba36c9764736f6c63430008110033",
    -  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046109e6565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103009050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b9250610167610107826005610a96565b61ffff9081169060059061011d9085168d610ab8565b6101279190610ab8565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b9150610227565b6101b260058b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103a99050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b925061022461020e826007610a96565b61ffff9081169060079061011d9085168d610ab8565b91505b6000606061026c84868a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103d192505050565b90925090508180156102f057506102916014825161028a9190610ab8565b82906103ec565b6bffffffffffffffffffffffff19166102df8b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061041f92505050565b6bffffffffffffffffffffffff1916145b9c9b505050505050505050505050565b600082828151811061031457610314610acb565b016020015160f81c90505b92915050565b82516060906103348385610ae1565b111561033f57600080fd5b60008267ffffffffffffffff81111561035a5761035a610af4565b6040519080825280601f01601f191660200182016040528015610384576020820181803683370190505b5090506020808201908686010161039c8282876108b0565b50909150505b9392505050565b81516000906103b9836002610ae1565b11156103c457600080fd5b50016002015161ffff1690565b600060606103e0838587610906565b91509150935093915050565b81516000906103fc836014610ae1565b111561040757600080fd5b5001602001516bffffffffffffffffffffffff191690565b60006040518251602084019350604067ffffffffffffffc060018301160160098282031060018103610452576040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f06104a4565b6000838310156103a2575080820151928290039260208410156103a25760001960208590036101000a0119169392505050565b60005b82811015610830576104ba848289610471565b85526104ca846020830189610471565b6020860152604081850310600181036104e65760808286038701535b506040830381146001810361050357602086018051600887021790525b5060405b608081101561058b57858101603f19810151603719820151601f19830151600b198401516002911891909218189081027ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe1663800000009091047c010000000100000001000000010000000100000001000000010000000116179052600c01610507565b5060805b61014081101561061457858101607f19810151606f19820151603f198301516017198401516004911891909218189081027ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc1663400000009091047c03000000030000000300000003000000030000000300000003000000031617905260180161058f565b508160008060005b60508110156108065760148104801561064c576001811461067c57600281146106aa57600381146106dd57610707565b6501000000000085046a010000000000000000000086048118600160781b870416189350635a8279999250610707565b650100000000008504600160781b86046a0100000000000000000000870418189350636ed9eba19250610707565b6a01000000000000000000008504600160781b8604818117650100000000008804169116179350638f1bbcdc9250610707565b650100000000008504600160781b86046a010000000000000000000087041818935063ca62c1d692505b50601f770800000000000000000000000000000000000000000000008504168063ffffffe073080000000000000000000000000000000000000087041617905080840190508063ffffffff86160190508083019050807c0100000000000000000000000000000000000000000000000000000000600484028c015104019050740100000000000000000000000000000000000000008102650100000000008604179450506a0100000000000000000000633fffffff6a040000000000000000000086041663c00000006604000000000000870416170277ffffffff00ffffffff000000000000ffffffff00ffffffff851617935060018101905061061c565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff16906040016104a7565b506c0100000000000000000000000063ffffffff821667ffffffff000000006101008404166bffffffff0000000000000000620100008504166fffffffff000000000000000000000000630100000086041673ffffffff000000000000000000000000000000006401000000008704161717171702945050505050919050565b602081106108e857815183526108c7602084610ae1565b92506108d4602083610ae1565b91506108e1602082610ab8565b90506108b0565b905182516020929092036101000a6000190180199091169116179052565b60006060600085518551855188888860405160200161092a96959493929190610b3a565b6040516020818303038152906040529050835167ffffffffffffffff81111561095557610955610af4565b6040519080825280601f01601f19166020018201604052801561097f576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b60008083601f8401126109af57600080fd5b50813567ffffffffffffffff8111156109c757600080fd5b6020830191508360208285010111156109df57600080fd5b9250929050565b600080600080600080606087890312156109ff57600080fd5b863567ffffffffffffffff80821115610a1757600080fd5b610a238a838b0161099d565b90985096506020890135915080821115610a3c57600080fd5b610a488a838b0161099d565b90965094506040890135915080821115610a6157600080fd5b50610a6e89828a0161099d565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b61ffff818116838216019080821115610ab157610ab1610a80565b5092915050565b8181038181111561031f5761031f610a80565b634e487b7160e01b600052603260045260246000fd5b8082018082111561031f5761031f610a80565b634e487b7160e01b600052604160045260246000fd5b6000815160005b81811015610b2b5760208185018101518683015201610b11565b50600093019283525090919050565b8681528560208201528460408201526000610b6a610b64610b5e6060850188610b0a565b86610b0a565b84610b0a565b9897505050505050505056fea26469706673582212207857b7c8a67e5fd64e3ccb8e7b2e6fbd8ac879a5659d7498b1bc12aeeba36c9764736f6c63430008110033",
    +  "contractName": "RSASHA1Algorithm",
    +  "sourceName": "contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol",
    +  "bytecode": "0x6080604052348015600f57600080fd5b506110c48061001f6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610eaf565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102c39050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b9250610167610107826005610f84565b61ffff9081169060059061011d9085168d610f9e565b6101279190610f9e565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b9150610227565b6101b260058b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103599050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b925061022461020e826007610f84565b61ffff9081169060079061011d9085168d610f9e565b91505b6102b5828488888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506102b08c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061037692505050565b610945565b9a9950505050505050505050565b60006102d9836102d4846001610fb1565b6109e2565b8282815181106102eb576102eb610fc4565b016020015160f81c90505b92915050565b60608167ffffffffffffffff81111561031757610317610ff3565b6040519080825280601f01601f191660200182016040528015610341576020820181803683370190505b509050610352848483600086610a37565b9392505050565b600061036a836102d4846002610fb1565b50016020015160f01c90565b60006040518251602084019350604067ffffffffffffffc0600183011601600982820310600181036103a9576040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f0610419565b60008383101561035257508082015192829003926020841015610352577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208590036101000a0119169392505050565b60005b828110156108c55761042f8482896103c8565b855261043f8460208301896103c8565b60208601526040818503106001810361045b5760808286038701535b506040830381146001810361047857602086018051600887021790525b5060405b6080811015610578578581017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc88201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff48401516002911891909218189081027ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe1663800000009091047c010000000100000001000000010000000100000001000000010000000116179052600c0161047c565b5060805b610140811015610679578581017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08301517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe88401516004911891909218189081027ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc1663400000009091047c03000000030000000300000003000000030000000300000003000000031617905260180161057c565b508160008060005b605081101561089b576014810480156106b157600181146106ed576002811461072757600381146107665761079c565b6501000000000085046a0100000000000000000000860481186f01000000000000000000000000000000870416189350635a827999925061079c565b6501000000000085046f0100000000000000000000000000000086046a0100000000000000000000870418189350636ed9eba1925061079c565b6a010000000000000000000085046f010000000000000000000000000000008604818117650100000000008804169116179350638f1bbcdc925061079c565b6501000000000085046f0100000000000000000000000000000086046a010000000000000000000087041818935063ca62c1d692505b50601f770800000000000000000000000000000000000000000000008504168063ffffffe073080000000000000000000000000000000000000087041617905080840190508063ffffffff86160190508083019050807c0100000000000000000000000000000000000000000000000000000000600484028c015104019050740100000000000000000000000000000000000000008102650100000000008604179450506a0100000000000000000000633fffffff6a040000000000000000000086041663c00000006604000000000000870416170277ffffffff00ffffffff000000000000ffffffff00ffffffff8516179350600181019050610681565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff169060400161041c565b506c0100000000000000000000000063ffffffff821667ffffffff000000006101008404166bffffffff0000000000000000620100008504166fffffffff000000000000000000000000630100000086041673ffffffff000000000000000000000000000000006401000000008704161717171702945050505050919050565b600080600061098b8787876040518060400160405280600f81526020017f3021300906052b0e03021a050004140000000000000000000000000000000000815250610a6f565b915091508180156109d757506109af601482516109a89190610f9e565b8290610cd4565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008581169116145b979650505050505050565b8151811115610a335781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610a2a918391600401918252602082015260400190565b60405180910390fd5b5050565b610a45856102d48387610fb1565b610a53836102d48385610fb1565b610a6882602085010185602088010183610cf1565b5050505050565b60006060600080610a81888888610d77565b91509150811580610a9457508751815114155b15610aa657600093509150610ccb9050565b80600081518110610ab957610ab9610fc4565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016151580610b47575080600181518110610afb57610afb610fc4565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f010000000000000000000000000000000000000000000000000000000000000014155b15610b5957600093509150610ccb9050565b60008551600f14610b6b576020610b6e565b60145b60ff1690506000818351610b829190610f9e565b90506000875182610b939190610f9e565b905083610ba1600183610f9e565b81518110610bb157610bb1610fc4565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615610bee57600084965096505050505050610ccb565b8751610c0290859083908b90600090610d92565b610c1757600084965096505050505050610ccb565b60006002610c26600184610f9e565b610c309190610f9e565b90506008811015610c4d5760008597509750505050505050610ccb565b60025b610c5b600184610f9e565b811015610cbd57858181518110610c7457610c74610fc4565b01602001517fff0000000000000000000000000000000000000000000000000000000000000090811614610cb5576000869850985050505050505050610ccb565b600101610c50565b506001975093955050505050505b94509492505050565b6000610ce5836102d4846014610fb1565b50016014015160601b90565b5b601f811115610d305781518352602092830192909101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001610cf2565b8015610d7257815183516001602084900360031b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161783525b505050565b60006060610d86838587610db5565b91509150935093915050565b6000610d9f848484610e4c565b610daa878785610e4c565b149695505050505050565b600060606000855185518551888888604051602001610dd996959493929190611052565b6040516020818303038152906040529050835167ffffffffffffffff811115610e0457610e04610ff3565b6040519080825280601f01601f191660200182016040528015610e2e576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b6000610e5c846102d48486610fb1565b5091016020012090565b60008083601f840112610e7857600080fd5b50813567ffffffffffffffff811115610e9057600080fd5b602083019150836020828501011115610ea857600080fd5b9250929050565b60008060008060008060608789031215610ec857600080fd5b863567ffffffffffffffff811115610edf57600080fd5b610eeb89828a01610e66565b909750955050602087013567ffffffffffffffff811115610f0b57600080fd5b610f1789828a01610e66565b909550935050604087013567ffffffffffffffff811115610f3757600080fd5b610f4389828a01610e66565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff81811683821601908111156102f6576102f6610f55565b818103818111156102f6576102f6610f55565b808201808211156102f6576102f6610f55565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000815160005b818110156110435760208185018101518683015201611029565b50600093019283525090919050565b868152856020820152846040820152600061108261107c6110766060850188611022565b86611022565b84611022565b9897505050505050505056fea264697066735822122016a90630cdc11b5bbd0fa46e4576311b3615cc9991b0025f3ed883bf3156890b64736f6c634300081a0033",
    +  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610eaf565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102c39050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b9250610167610107826005610f84565b61ffff9081169060059061011d9085168d610f9e565b6101279190610f9e565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b9150610227565b6101b260058b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103599050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b925061022461020e826007610f84565b61ffff9081169060079061011d9085168d610f9e565b91505b6102b5828488888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506102b08c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061037692505050565b610945565b9a9950505050505050505050565b60006102d9836102d4846001610fb1565b6109e2565b8282815181106102eb576102eb610fc4565b016020015160f81c90505b92915050565b60608167ffffffffffffffff81111561031757610317610ff3565b6040519080825280601f01601f191660200182016040528015610341576020820181803683370190505b509050610352848483600086610a37565b9392505050565b600061036a836102d4846002610fb1565b50016020015160f01c90565b60006040518251602084019350604067ffffffffffffffc0600183011601600982820310600181036103a9576040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f0610419565b60008383101561035257508082015192829003926020841015610352577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208590036101000a0119169392505050565b60005b828110156108c55761042f8482896103c8565b855261043f8460208301896103c8565b60208601526040818503106001810361045b5760808286038701535b506040830381146001810361047857602086018051600887021790525b5060405b6080811015610578578581017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc88201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff48401516002911891909218189081027ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe1663800000009091047c010000000100000001000000010000000100000001000000010000000116179052600c0161047c565b5060805b610140811015610679578581017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08301517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe88401516004911891909218189081027ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc1663400000009091047c03000000030000000300000003000000030000000300000003000000031617905260180161057c565b508160008060005b605081101561089b576014810480156106b157600181146106ed576002811461072757600381146107665761079c565b6501000000000085046a0100000000000000000000860481186f01000000000000000000000000000000870416189350635a827999925061079c565b6501000000000085046f0100000000000000000000000000000086046a0100000000000000000000870418189350636ed9eba1925061079c565b6a010000000000000000000085046f010000000000000000000000000000008604818117650100000000008804169116179350638f1bbcdc925061079c565b6501000000000085046f0100000000000000000000000000000086046a010000000000000000000087041818935063ca62c1d692505b50601f770800000000000000000000000000000000000000000000008504168063ffffffe073080000000000000000000000000000000000000087041617905080840190508063ffffffff86160190508083019050807c0100000000000000000000000000000000000000000000000000000000600484028c015104019050740100000000000000000000000000000000000000008102650100000000008604179450506a0100000000000000000000633fffffff6a040000000000000000000086041663c00000006604000000000000870416170277ffffffff00ffffffff000000000000ffffffff00ffffffff8516179350600181019050610681565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff169060400161041c565b506c0100000000000000000000000063ffffffff821667ffffffff000000006101008404166bffffffff0000000000000000620100008504166fffffffff000000000000000000000000630100000086041673ffffffff000000000000000000000000000000006401000000008704161717171702945050505050919050565b600080600061098b8787876040518060400160405280600f81526020017f3021300906052b0e03021a050004140000000000000000000000000000000000815250610a6f565b915091508180156109d757506109af601482516109a89190610f9e565b8290610cd4565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008581169116145b979650505050505050565b8151811115610a335781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610a2a918391600401918252602082015260400190565b60405180910390fd5b5050565b610a45856102d48387610fb1565b610a53836102d48385610fb1565b610a6882602085010185602088010183610cf1565b5050505050565b60006060600080610a81888888610d77565b91509150811580610a9457508751815114155b15610aa657600093509150610ccb9050565b80600081518110610ab957610ab9610fc4565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016151580610b47575080600181518110610afb57610afb610fc4565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f010000000000000000000000000000000000000000000000000000000000000014155b15610b5957600093509150610ccb9050565b60008551600f14610b6b576020610b6e565b60145b60ff1690506000818351610b829190610f9e565b90506000875182610b939190610f9e565b905083610ba1600183610f9e565b81518110610bb157610bb1610fc4565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615610bee57600084965096505050505050610ccb565b8751610c0290859083908b90600090610d92565b610c1757600084965096505050505050610ccb565b60006002610c26600184610f9e565b610c309190610f9e565b90506008811015610c4d5760008597509750505050505050610ccb565b60025b610c5b600184610f9e565b811015610cbd57858181518110610c7457610c74610fc4565b01602001517fff0000000000000000000000000000000000000000000000000000000000000090811614610cb5576000869850985050505050505050610ccb565b600101610c50565b506001975093955050505050505b94509492505050565b6000610ce5836102d4846014610fb1565b50016014015160601b90565b5b601f811115610d305781518352602092830192909101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001610cf2565b8015610d7257815183516001602084900360031b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161783525b505050565b60006060610d86838587610db5565b91509150935093915050565b6000610d9f848484610e4c565b610daa878785610e4c565b149695505050505050565b600060606000855185518551888888604051602001610dd996959493929190611052565b6040516020818303038152906040529050835167ffffffffffffffff811115610e0457610e04610ff3565b6040519080825280601f01601f191660200182016040528015610e2e576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b6000610e5c846102d48486610fb1565b5091016020012090565b60008083601f840112610e7857600080fd5b50813567ffffffffffffffff811115610e9057600080fd5b602083019150836020828501011115610ea857600080fd5b9250929050565b60008060008060008060608789031215610ec857600080fd5b863567ffffffffffffffff811115610edf57600080fd5b610eeb89828a01610e66565b909750955050602087013567ffffffffffffffff811115610f0b57600080fd5b610f1789828a01610e66565b909550935050604087013567ffffffffffffffff811115610f3757600080fd5b610f4389828a01610e66565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff81811683821601908111156102f6576102f6610f55565b818103818111156102f6576102f6610f55565b808201808211156102f6576102f6610f55565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000815160005b818110156110435760208185018101518683015201611029565b50600093019283525090919050565b868152856020820152846040820152600061108261107c6110766060850188611022565b86611022565b84611022565b9897505050505050505056fea264697066735822122016a90630cdc11b5bbd0fa46e4576311b3615cc9991b0025f3ed883bf3156890b64736f6c634300081a0033",
    +  "linkReferences": {},
    +  "deployedLinkReferences": {},
    +  "immutableReferences": {},
    +  "inputSourceName": "project/contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol",
       "devdoc": {
         "details": "Implements the DNSSEC RSASHA1 algorithm.",
    +    "errors": {
    +      "OffsetOutOfBoundsError(uint256,uint256)": [
    +        {
    +          "details": "`offset` was beyond `length`.       Error selector: `0x8a3c1cfb`"
    +        }
    +      ]
    +    },
         "kind": "dev",
         "methods": {},
         "version": 1
       },
    +  "evm": {
    +    "gasEstimates": {
    +      "creation": {
    +        "codeDepositCost": "858400",
    +        "executionCost": "896",
    +        "totalCost": "859296"
    +      },
    +      "external": {
    +        "verify(bytes,bytes,bytes)": "infinite"
    +      }
    +    }
    +  },
    +  "metadata": "{\"compiler\":{\"version\":\"0.8.26+commit.8a97fa7a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements the DNSSEC RSASHA1 algorithm.\",\"errors\":{\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`.       Error selector: `0x8a3c1cfb`\"}]},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol\":\"RSASHA1Algorithm\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[\"project/:@ensdomains/solsha1/=npm/@ensdomains/solsha1@0.0.3/\"]},\"sources\":{\"npm/@ensdomains/solsha1@0.0.3/contracts/SHA1.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary SHA1 {\\n    event Debug(bytes32 x);\\n\\n    function sha1(bytes memory data) internal pure returns(bytes20 ret) {\\n        assembly {\\n            // Get a safe scratch location\\n            let scratch := mload(0x40)\\n\\n            // Get the data length, and point data at the first byte\\n            let len := mload(data)\\n            data := add(data, 32)\\n\\n            // Find the length after padding\\n            let totallen := add(and(add(len, 1), 0xFFFFFFFFFFFFFFC0), 64)\\n            switch lt(sub(totallen, len), 9)\\n            case 1 { totallen := add(totallen, 64) }\\n\\n            let h := 0x6745230100EFCDAB890098BADCFE001032547600C3D2E1F0\\n\\n            function readword(ptr, off, count) -> result {\\n                result := 0\\n                if lt(off, count) {\\n                    result := mload(add(ptr, off))\\n                    count := sub(count, off)\\n                    if lt(count, 32) {\\n                        let mask := not(sub(exp(256, sub(32, count)), 1))\\n                        result := and(result, mask)\\n                    }\\n                }\\n            }\\n\\n            for { let i := 0 } lt(i, totallen) { i := add(i, 64) } {\\n                mstore(scratch, readword(data, i, len))\\n                mstore(add(scratch, 32), readword(data, add(i, 32), len))\\n\\n                // If we loaded the last byte, store the terminator byte\\n                switch lt(sub(len, i), 64)\\n                case 1 { mstore8(add(scratch, sub(len, i)), 0x80) }\\n\\n                // If this is the last block, store the length\\n                switch eq(i, sub(totallen, 64))\\n                case 1 { mstore(add(scratch, 32), or(mload(add(scratch, 32)), mul(len, 8))) }\\n\\n                // Expand the 16 32-bit words into 80\\n                for { let j := 64 } lt(j, 128) { j := add(j, 12) } {\\n                    let temp := xor(xor(mload(add(scratch, sub(j, 12))), mload(add(scratch, sub(j, 32)))), xor(mload(add(scratch, sub(j, 56))), mload(add(scratch, sub(j, 64)))))\\n                    temp := or(and(mul(temp, 2), 0xFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE), and(div(temp, 0x80000000), 0x0000000100000001000000010000000100000001000000010000000100000001))\\n                    mstore(add(scratch, j), temp)\\n                }\\n                for { let j := 128 } lt(j, 320) { j := add(j, 24) } {\\n                    let temp := xor(xor(mload(add(scratch, sub(j, 24))), mload(add(scratch, sub(j, 64)))), xor(mload(add(scratch, sub(j, 112))), mload(add(scratch, sub(j, 128)))))\\n                    temp := or(and(mul(temp, 4), 0xFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFC), and(div(temp, 0x40000000), 0x0000000300000003000000030000000300000003000000030000000300000003))\\n                    mstore(add(scratch, j), temp)\\n                }\\n\\n                let x := h\\n                let f := 0\\n                let k := 0\\n                for { let j := 0 } lt(j, 80) { j := add(j, 1) } {\\n                    switch div(j, 20)\\n                    case 0 {\\n                        // f = d xor (b and (c xor d))\\n                        f := xor(div(x, 0x100000000000000000000), div(x, 0x10000000000))\\n                        f := and(div(x, 0x1000000000000000000000000000000), f)\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0x5A827999\\n                    }\\n                    case 1{\\n                        // f = b xor c xor d\\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0x6ED9EBA1\\n                    }\\n                    case 2 {\\n                        // f = (b and c) or (d and (b or c))\\n                        f := or(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := and(div(x, 0x10000000000), f)\\n                        f := or(and(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000)), f)\\n                        k := 0x8F1BBCDC\\n                    }\\n                    case 3 {\\n                        // f = b xor c xor d\\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0xCA62C1D6\\n                    }\\n                    // temp = (a leftrotate 5) + f + e + k + w[i]\\n                    let temp := and(div(x, 0x80000000000000000000000000000000000000000000000), 0x1F)\\n                    temp := or(and(div(x, 0x800000000000000000000000000000000000000), 0xFFFFFFE0), temp)\\n                    temp := add(f, temp)\\n                    temp := add(and(x, 0xFFFFFFFF), temp)\\n                    temp := add(k, temp)\\n                    temp := add(div(mload(add(scratch, mul(j, 4))), 0x100000000000000000000000000000000000000000000000000000000), temp)\\n                    x := or(div(x, 0x10000000000), mul(temp, 0x10000000000000000000000000000000000000000))\\n                    x := or(and(x, 0xFFFFFFFF00FFFFFFFF000000000000FFFFFFFF00FFFFFFFF), mul(or(and(div(x, 0x4000000000000), 0xC0000000), and(div(x, 0x400000000000000000000), 0x3FFFFFFF)), 0x100000000000000000000))\\n                }\\n\\n                h := and(add(h, x), 0xFFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF)\\n            }\\n            ret := mul(or(or(or(or(and(div(h, 0x100000000), 0xFFFFFFFF00000000000000000000000000000000), and(div(h, 0x1000000), 0xFFFFFFFF000000000000000000000000)), and(div(h, 0x10000), 0xFFFFFFFF0000000000000000)), and(div(h, 0x100), 0xFFFFFFFF00000000)), and(h, 0xFFFFFFFF)), 0x1000000000000000000000000)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x746d9b85de197afbc13182cbe4ba4f7917f19594e07c655d6a0c85fdf7460a8a\"},\"project/contracts/dnssec-oracle/algorithms/Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/// @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\\ninterface Algorithm {\\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    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xbcbdc06d72b64903e733e7ddfbf59c35c984c3eb0022baacab12c97292cc13df\"},\"project/contracts/dnssec-oracle/algorithms/ModexpPrecompile.sol\":{\"content\":\"pragma solidity ^0.8.4
    ... [truncated]
    
  • deployments/mainnet/RSASHA256Algorithm.json+59 26 modified
    @@ -1,6 +1,22 @@
     {
    -  "address": "0x9D1B5a639597f558bC37Cf81813724076c5C1e96",
    +  "address": "0xaee0e2c4d5ab2fc164c8b0cc8d3118c1c752c95e",
       "abi": [
    +    {
    +      "inputs": [
    +        {
    +          "internalType": "uint256",
    +          "name": "offset",
    +          "type": "uint256"
    +        },
    +        {
    +          "internalType": "uint256",
    +          "name": "length",
    +          "type": "uint256"
    +        }
    +      ],
    +      "name": "OffsetOutOfBoundsError",
    +      "type": "error"
    +    },
         {
           "inputs": [
             {
    @@ -31,41 +47,58 @@
           "type": "function"
         }
       ],
    -  "transactionHash": "0x3bfc4088c954a7fd47fc5bc40fb0affdb5ca8369229e307e12019da09cee3665",
    -  "receipt": {
    -    "to": null,
    -    "from": "0x0904Dac3347eA47d208F3Fd67402D039a3b99859",
    -    "contractAddress": "0x9D1B5a639597f558bC37Cf81813724076c5C1e96",
    -    "transactionIndex": 33,
    -    "gasUsed": "448967",
    -    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    -    "blockHash": "0x386dd045029097dd9139f841cbf593572c54b455e846186854148c9fe4db391f",
    -    "transactionHash": "0x3bfc4088c954a7fd47fc5bc40fb0affdb5ca8369229e307e12019da09cee3665",
    -    "logs": [],
    -    "blockNumber": 19020682,
    -    "cumulativeGasUsed": "3660506",
    -    "status": 1,
    -    "byzantium": true
    -  },
    -  "args": [],
    -  "numDeployments": 2,
    -  "solcInputHash": "dd9e022689821cffaeb04b9ddbda87ae",
    -  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements the DNSSEC RSASHA256 algorithm.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol\":\"RSASHA256Algorithm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"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/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/algorithms/ModexpPrecompile.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary ModexpPrecompile {\\n    /**\\n     * @dev Computes (base ^ exponent) % modulus over big numbers.\\n     */\\n    function modexp(\\n        bytes memory base,\\n        bytes memory exponent,\\n        bytes memory modulus\\n    ) internal view returns (bool success, bytes memory output) {\\n        bytes memory input = abi.encodePacked(\\n            uint256(base.length),\\n            uint256(exponent.length),\\n            uint256(modulus.length),\\n            base,\\n            exponent,\\n            modulus\\n        );\\n\\n        output = new bytes(modulus.length);\\n\\n        assembly {\\n            success := staticcall(\\n                gas(),\\n                5,\\n                add(input, 32),\\n                mload(input),\\n                add(output, 32),\\n                mload(modulus)\\n            )\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xb3d46284534eb99061d4c79968c2d0420b63a6649d118ef2ea3608396b85de3f\"},\"contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"../BytesUtils.sol\\\";\\nimport \\\"./RSAVerify.sol\\\";\\n\\n/**\\n * @dev Implements the DNSSEC RSASHA256 algorithm.\\n */\\ncontract RSASHA256Algorithm is Algorithm {\\n    using BytesUtils for *;\\n\\n    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata sig\\n    ) external view override returns (bool) {\\n        bytes memory exponent;\\n        bytes memory modulus;\\n\\n        uint16 exponentLen = uint16(key.readUint8(4));\\n        if (exponentLen != 0) {\\n            exponent = key.substring(5, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 5,\\n                key.length - exponentLen - 5\\n            );\\n        } else {\\n            exponentLen = key.readUint16(5);\\n            exponent = key.substring(7, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 7,\\n                key.length - exponentLen - 7\\n            );\\n        }\\n\\n        // Recover the message from the signature\\n        bool ok;\\n        bytes memory result;\\n        (ok, result) = RSAVerify.rsarecover(modulus, exponent, sig);\\n\\n        // Verify it ends with the hash of our data\\n        return ok && sha256(data) == result.readBytes32(result.length - 32);\\n    }\\n}\\n\",\"keccak256\":\"0x1d6ba44f41e957f9c53e6e5b88150cbb6c9f46e9da196502984ee0a53e9ac5a9\"},\"contracts/dnssec-oracle/algorithms/RSAVerify.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"../BytesUtils.sol\\\";\\nimport \\\"./ModexpPrecompile.sol\\\";\\n\\nlibrary RSAVerify {\\n    /**\\n     * @dev Recovers the input data from an RSA signature, returning the result in S.\\n     * @param N The RSA public modulus.\\n     * @param E The RSA public exponent.\\n     * @param S The signature to recover.\\n     * @return True if the recovery succeeded.\\n     */\\n    function rsarecover(\\n        bytes memory N,\\n        bytes memory E,\\n        bytes memory S\\n    ) internal view returns (bool, bytes memory) {\\n        return ModexpPrecompile.modexp(S, E, N);\\n    }\\n}\\n\",\"keccak256\":\"0xb386daa80070f79399a2cb97a534f31660161ccd50662fabcf63e26cce064506\"}},\"version\":1}",
    -  "bytecode": "0x608060405234801561001057600080fd5b50610728806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610539565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102f59050565b60ff169050801561016e576100f760058261ffff168c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b92506101676101078260056105e9565b61ffff9081169060059061011d9085168d61060b565b610127919061060b565b8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b9150610227565b6101b260058b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061039c9050565b90506101fe60078261ffff168c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b925061022461020e8260076105e9565b61ffff9081169060079061011d9085168d61060b565b91505b6000606061026c84868a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103c492505050565b90925090508180156102e557506102916020825161028a919061060b565b82906103df565b60028b8b6040516102a392919061061e565b602060405180830381855afa1580156102c0573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906102e3919061062e565b145b9c9b505050505050505050505050565b600082828151811061030957610309610647565b016020015160f81c90505b92915050565b8251606090610329838561065d565b111561033457600080fd5b60008267ffffffffffffffff81111561034f5761034f610670565b6040519080825280601f01601f191660200182016040528015610379576020820181803683370190505b50905060208082019086860101610391828287610403565b509095945050505050565b81516000906103ac83600261065d565b11156103b757600080fd5b50016002015161ffff1690565b600060606103d3838587610459565b91509150935093915050565b81516000906103ef83602061065d565b11156103fa57600080fd5b50016020015190565b6020811061043b578151835261041a60208461065d565b925061042760208361065d565b915061043460208261060b565b9050610403565b905182516020929092036101000a6000190180199091169116179052565b60006060600085518551855188888860405160200161047d969594939291906106b6565b6040516020818303038152906040529050835167ffffffffffffffff8111156104a8576104a8610670565b6040519080825280601f01601f1916602001820160405280156104d2576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b60008083601f84011261050257600080fd5b50813567ffffffffffffffff81111561051a57600080fd5b60208301915083602082850101111561053257600080fd5b9250929050565b6000806000806000806060878903121561055257600080fd5b863567ffffffffffffffff8082111561056a57600080fd5b6105768a838b016104f0565b9098509650602089013591508082111561058f57600080fd5b61059b8a838b016104f0565b909650945060408901359150808211156105b457600080fd5b506105c189828a016104f0565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b61ffff818116838216019080821115610604576106046105d3565b5092915050565b81810381811115610314576103146105d3565b8183823760009101908152919050565b60006020828403121561064057600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b80820180821115610314576103146105d3565b634e487b7160e01b600052604160045260246000fd5b6000815160005b818110156106a7576020818501810151868301520161068d565b50600093019283525090919050565b86815285602082015284604082015260006106e66106e06106da6060850188610686565b86610686565b84610686565b9897505050505050505056fea264697066735822122081d54f6872821586c976d8d9aa106e2ea811afa445a713b0da099f753dd8e48364736f6c63430008110033",
    -  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610539565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102f59050565b60ff169050801561016e576100f760058261ffff168c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b92506101676101078260056105e9565b61ffff9081169060059061011d9085168d61060b565b610127919061060b565b8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b9150610227565b6101b260058b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061039c9050565b90506101fe60078261ffff168c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b925061022461020e8260076105e9565b61ffff9081169060079061011d9085168d61060b565b91505b6000606061026c84868a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103c492505050565b90925090508180156102e557506102916020825161028a919061060b565b82906103df565b60028b8b6040516102a392919061061e565b602060405180830381855afa1580156102c0573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906102e3919061062e565b145b9c9b505050505050505050505050565b600082828151811061030957610309610647565b016020015160f81c90505b92915050565b8251606090610329838561065d565b111561033457600080fd5b60008267ffffffffffffffff81111561034f5761034f610670565b6040519080825280601f01601f191660200182016040528015610379576020820181803683370190505b50905060208082019086860101610391828287610403565b509095945050505050565b81516000906103ac83600261065d565b11156103b757600080fd5b50016002015161ffff1690565b600060606103d3838587610459565b91509150935093915050565b81516000906103ef83602061065d565b11156103fa57600080fd5b50016020015190565b6020811061043b578151835261041a60208461065d565b925061042760208361065d565b915061043460208261060b565b9050610403565b905182516020929092036101000a6000190180199091169116179052565b60006060600085518551855188888860405160200161047d969594939291906106b6565b6040516020818303038152906040529050835167ffffffffffffffff8111156104a8576104a8610670565b6040519080825280601f01601f1916602001820160405280156104d2576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b60008083601f84011261050257600080fd5b50813567ffffffffffffffff81111561051a57600080fd5b60208301915083602082850101111561053257600080fd5b9250929050565b6000806000806000806060878903121561055257600080fd5b863567ffffffffffffffff8082111561056a57600080fd5b6105768a838b016104f0565b9098509650602089013591508082111561058f57600080fd5b61059b8a838b016104f0565b909650945060408901359150808211156105b457600080fd5b506105c189828a016104f0565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b61ffff818116838216019080821115610604576106046105d3565b5092915050565b81810381811115610314576103146105d3565b8183823760009101908152919050565b60006020828403121561064057600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b80820180821115610314576103146105d3565b634e487b7160e01b600052604160045260246000fd5b6000815160005b818110156106a7576020818501810151868301520161068d565b50600093019283525090919050565b86815285602082015284604082015260006106e66106e06106da6060850188610686565b86610686565b84610686565b9897505050505050505056fea264697066735822122081d54f6872821586c976d8d9aa106e2ea811afa445a713b0da099f753dd8e48364736f6c63430008110033",
    +  "contractName": "RSASHA256Algorithm",
    +  "sourceName": "contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol",
    +  "bytecode": "0x6080604052348015600f57600080fd5b50610afb8061001f6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046108bd565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102c89050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b9250610167610107826005610992565b61ffff9081169060059061011d9085168d6109ac565b61012791906109ac565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b9150610227565b6101b260058b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061035e9050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b925061022461020e826007610992565b61ffff9081169060079061011d9085168d6109ac565b91505b6102ba828488888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040516002925061027591508e908e906109bf565b602060405180830381855afa158015610292573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906102b591906109cf565b61037b565b9a9950505050505050505050565b60006102de836102d98460016109e8565b6103f3565b8282815181106102f0576102f06109fb565b016020015160f81c90505b92915050565b60608167ffffffffffffffff81111561031c5761031c610a2a565b6040519080825280601f01601f191660200182016040528015610346576020820181803683370190505b509050610357848483600086610448565b9392505050565b600061036f836102d98460026109e8565b50016020015160f01c90565b60008060006103c18787876040518060400160405280601381526020017f3031300d06096086480165030402010500042000000000000000000000000000815250610480565b915091508180156103e857506103e5602082516103de91906109ac565b82906106e5565b84145b979650505050505050565b81518111156104445781516040517f8a3c1cfb00000000000000000000000000000000000000000000000000000000815261043b918391600401918252602082015260400190565b60405180910390fd5b5050565b610456856102d983876109e8565b610464836102d983856109e8565b610479826020850101856020880101836106ff565b5050505050565b60006060600080610492888888610785565b915091508115806104a557508751815114155b156104b7576000935091506106dc9050565b806000815181106104ca576104ca6109fb565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615158061055857508060018151811061050c5761050c6109fb565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f010000000000000000000000000000000000000000000000000000000000000014155b1561056a576000935091506106dc9050565b60008551600f1461057c57602061057f565b60145b60ff169050600081835161059391906109ac565b905060008751826105a491906109ac565b9050836105b26001836109ac565b815181106105c2576105c26109fb565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016156105ff576000849650965050505050506106dc565b875161061390859083908b906000906107a0565b610628576000849650965050505050506106dc565b600060026106376001846109ac565b61064191906109ac565b9050600881101561065e57600085975097505050505050506106dc565b60025b61066c6001846109ac565b8110156106ce57858181518110610685576106856109fb565b01602001517fff00000000000000000000000000000000000000000000000000000000000000908116146106c65760008698509850505050505050506106dc565b600101610661565b506001975093955050505050505b94509492505050565b60006106f6836102d98460206109e8565b50016020015190565b5b601f81111561073e5781518352602092830192909101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001610700565b801561078057815183516001602084900360031b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161783525b505050565b600060606107948385876107c3565b91509150935093915050565b60006107ad84848461085a565b6107b887878561085a565b149695505050505050565b6000606060008551855185518888886040516020016107e796959493929190610a89565b6040516020818303038152906040529050835167ffffffffffffffff81111561081257610812610a2a565b6040519080825280601f01601f19166020018201604052801561083c576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b600061086a846102d984866109e8565b5091016020012090565b60008083601f84011261088657600080fd5b50813567ffffffffffffffff81111561089e57600080fd5b6020830191508360208285010111156108b657600080fd5b9250929050565b600080600080600080606087890312156108d657600080fd5b863567ffffffffffffffff8111156108ed57600080fd5b6108f989828a01610874565b909750955050602087013567ffffffffffffffff81111561091957600080fd5b61092589828a01610874565b909550935050604087013567ffffffffffffffff81111561094557600080fd5b61095189828a01610874565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff81811683821601908111156102fb576102fb610963565b818103818111156102fb576102fb610963565b8183823760009101908152919050565b6000602082840312156109e157600080fd5b5051919050565b808201808211156102fb576102fb610963565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000815160005b81811015610a7a5760208185018101518683015201610a60565b50600093019283525090919050565b8681528560208201528460408201526000610ab9610ab3610aad6060850188610a59565b86610a59565b84610a59565b9897505050505050505056fea2646970667358221220335ba623c7b8866af790ac308322c39a6ebbb7d4fae75897391e659f245c261264736f6c634300081a0033",
    +  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046108bd565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102c89050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b9250610167610107826005610992565b61ffff9081169060059061011d9085168d6109ac565b61012791906109ac565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b9150610227565b6101b260058b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061035e9050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b925061022461020e826007610992565b61ffff9081169060079061011d9085168d6109ac565b91505b6102ba828488888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040516002925061027591508e908e906109bf565b602060405180830381855afa158015610292573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906102b591906109cf565b61037b565b9a9950505050505050505050565b60006102de836102d98460016109e8565b6103f3565b8282815181106102f0576102f06109fb565b016020015160f81c90505b92915050565b60608167ffffffffffffffff81111561031c5761031c610a2a565b6040519080825280601f01601f191660200182016040528015610346576020820181803683370190505b509050610357848483600086610448565b9392505050565b600061036f836102d98460026109e8565b50016020015160f01c90565b60008060006103c18787876040518060400160405280601381526020017f3031300d06096086480165030402010500042000000000000000000000000000815250610480565b915091508180156103e857506103e5602082516103de91906109ac565b82906106e5565b84145b979650505050505050565b81518111156104445781516040517f8a3c1cfb00000000000000000000000000000000000000000000000000000000815261043b918391600401918252602082015260400190565b60405180910390fd5b5050565b610456856102d983876109e8565b610464836102d983856109e8565b610479826020850101856020880101836106ff565b5050505050565b60006060600080610492888888610785565b915091508115806104a557508751815114155b156104b7576000935091506106dc9050565b806000815181106104ca576104ca6109fb565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615158061055857508060018151811061050c5761050c6109fb565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f010000000000000000000000000000000000000000000000000000000000000014155b1561056a576000935091506106dc9050565b60008551600f1461057c57602061057f565b60145b60ff169050600081835161059391906109ac565b905060008751826105a491906109ac565b9050836105b26001836109ac565b815181106105c2576105c26109fb565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016156105ff576000849650965050505050506106dc565b875161061390859083908b906000906107a0565b610628576000849650965050505050506106dc565b600060026106376001846109ac565b61064191906109ac565b9050600881101561065e57600085975097505050505050506106dc565b60025b61066c6001846109ac565b8110156106ce57858181518110610685576106856109fb565b01602001517fff00000000000000000000000000000000000000000000000000000000000000908116146106c65760008698509850505050505050506106dc565b600101610661565b506001975093955050505050505b94509492505050565b60006106f6836102d98460206109e8565b50016020015190565b5b601f81111561073e5781518352602092830192909101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001610700565b801561078057815183516001602084900360031b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161783525b505050565b600060606107948385876107c3565b91509150935093915050565b60006107ad84848461085a565b6107b887878561085a565b149695505050505050565b6000606060008551855185518888886040516020016107e796959493929190610a89565b6040516020818303038152906040529050835167ffffffffffffffff81111561081257610812610a2a565b6040519080825280601f01601f19166020018201604052801561083c576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b600061086a846102d984866109e8565b5091016020012090565b60008083601f84011261088657600080fd5b50813567ffffffffffffffff81111561089e57600080fd5b6020830191508360208285010111156108b657600080fd5b9250929050565b600080600080600080606087890312156108d657600080fd5b863567ffffffffffffffff8111156108ed57600080fd5b6108f989828a01610874565b909750955050602087013567ffffffffffffffff81111561091957600080fd5b61092589828a01610874565b909550935050604087013567ffffffffffffffff81111561094557600080fd5b61095189828a01610874565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff81811683821601908111156102fb576102fb610963565b818103818111156102fb576102fb610963565b8183823760009101908152919050565b6000602082840312156109e157600080fd5b5051919050565b808201808211156102fb576102fb610963565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000815160005b81811015610a7a5760208185018101518683015201610a60565b50600093019283525090919050565b8681528560208201528460408201526000610ab9610ab3610aad6060850188610a59565b86610a59565b84610a59565b9897505050505050505056fea2646970667358221220335ba623c7b8866af790ac308322c39a6ebbb7d4fae75897391e659f245c261264736f6c634300081a0033",
    +  "linkReferences": {},
    +  "deployedLinkReferences": {},
    +  "immutableReferences": {},
    +  "inputSourceName": "project/contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol",
       "devdoc": {
         "details": "Implements the DNSSEC RSASHA256 algorithm.",
    +    "errors": {
    +      "OffsetOutOfBoundsError(uint256,uint256)": [
    +        {
    +          "details": "`offset` was beyond `length`.       Error selector: `0x8a3c1cfb`"
    +        }
    +      ]
    +    },
         "kind": "dev",
         "methods": {},
         "version": 1
       },
    +  "evm": {
    +    "gasEstimates": {
    +      "creation": {
    +        "codeDepositCost": "562200",
    +        "executionCost": "594",
    +        "totalCost": "562794"
    +      },
    +      "external": {
    +        "verify(bytes,bytes,bytes)": "infinite"
    +      }
    +    }
    +  },
    +  "metadata": "{\"compiler\":{\"version\":\"0.8.26+commit.8a97fa7a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements the DNSSEC RSASHA256 algorithm.\",\"errors\":{\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`.       Error selector: `0x8a3c1cfb`\"}]},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol\":\"RSASHA256Algorithm\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[\"project/:@ensdomains/solsha1/=npm/@ensdomains/solsha1@0.0.3/\"]},\"sources\":{\"project/contracts/dnssec-oracle/algorithms/Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/// @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\\ninterface Algorithm {\\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    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xbcbdc06d72b64903e733e7ddfbf59c35c984c3eb0022baacab12c97292cc13df\"},\"project/contracts/dnssec-oracle/algorithms/ModexpPrecompile.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary ModexpPrecompile {\\n    /// @dev Computes (base ^ exponent) % modulus over big numbers.\\n    function modexp(\\n        bytes memory base,\\n        bytes memory exponent,\\n        bytes memory modulus\\n    ) internal view returns (bool success, bytes memory output) {\\n        bytes memory input = abi.encodePacked(\\n            uint256(base.length),\\n            uint256(exponent.length),\\n            uint256(modulus.length),\\n            base,\\n            exponent,\\n            modulus\\n        );\\n\\n        output = new bytes(modulus.length);\\n\\n        assembly {\\n            success := staticcall(\\n                gas(),\\n                5,\\n                add(input, 32),\\n                mload(input),\\n                add(output, 32),\\n                mload(modulus)\\n            )\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x06457e4fc1eda1e2ba6ef08cb270983756e760bdeaa3155e1ca69a5f4bc5dd1f\"},\"project/contracts/dnssec-oracle/algorithms/RSAPKCS1Verify.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./RSAVerify.sol\\\";\\nimport \\\"../../utils/BytesUtils.sol\\\";\\n\\n/// @dev Library for PKCS#1 v1.5 signature verification\\nlibrary RSAPKCS1Verify {\\n    using BytesUtils for *;\\n\\n    /// @dev PKCS#1 v1.5 DigestInfo prefix for SHA-1\\n    bytes constant SHA1_DIGEST_INFO = hex\\\"3021300906052b0e03021a05000414\\\";\\n\\n    /// @dev PKCS#1 v1.5 DigestInfo prefix for SHA-256\\n    bytes constant SHA256_DIGEST_INFO = hex\\\"3031300d060960864801650304020105000420\\\";\\n\\n    /// @dev Verifies an RSA signature with PKCS#1 v1.5 padding for SHA-1\\n    function verifySHA1(\\n        bytes memory modulus,\\n        bytes memory exponent,\\n        bytes memory sig,\\n        bytes20 hash\\n    ) internal view returns (bool) {\\n        (bool ok, bytes memory result) = recoverAndVerify(modulus, exponent, sig, SHA1_DIGEST_INFO);\\n        return ok && hash == result.readBytes20(result.length - 20);\\n    }\\n\\n    /// @dev Verifies an RSA signature with PKCS#1 v1.5 padding for SHA-256\\n    function verifySHA256(\\n        bytes memory modulus,\\n        bytes memory exponent,\\n        bytes memory sig,\\n        bytes32 hash\\n    ) internal view returns (bool) {\\n        (bool ok, bytes memory result) = recoverAndVerify(modulus, exponent, sig, SHA256_DIGEST_INFO);\\n        return ok && hash == result.readBytes32(result.length - 32);\\n    }\\n\\n    /// @dev Recovers RSA signature and verifies PKCS#1 v1.5 structure\\n    /// Format: 0x00 0x01 [0xFF padding] 0x00 [DigestInfo] [Hash]\\n    /// https://datatracker.ietf.org/doc/html/rfc8017#section-9.2\\n    function recoverAndVerify(\\n        bytes memory modulus,\\n        bytes memory exponent,\\n        bytes memory sig,\\n        bytes memory digestInfo\\n    ) private view returns (bool, bytes memory) {\\n        (bool ok, bytes memory result) = RSAVerify.rsarecover(modulus, exponent, sig);\\n        if (!ok || result.length != modulus.length) {\\n            return (false, result);\\n        }\\n\\n        // Check leading bytes: 0x00 0x01\\n        if (result[0] != 0x00 || result[1] != 0x01) {\\n            return (false, result);\\n        }\\n\\n        // Calculate positions working backwards from the end\\n        uint256 hashLen = digestInfo.length == 15 ? 20 : 32;\\n        uint256 hashStart = result.length - hashLen;\\n        uint256 digestInfoStart = hashStart - digestInfo.length;\\n\\n        // Verify 0x00 separator before DigestInfo\\n        if (result[digestInfoStart - 1] != 0x00) {\\n            return (false, result);\\n        }\\n\\n        // Verify DigestInfo matches expected value\\n        if (!result.equals(digestInfoStart, digestInfo, 0, digestInfo.length)) {\\n            return (false, result);\\n        }\\n\\n        // Verify padding: all bytes from position 2 to separator must be 0xFF\\n        // Minimum 8 bytes of 0xFF padding required (RFC 3447)\\n        uint256 paddingLen = digestInfoStart - 1 - 2;\\n        if (paddingLen < 8) {\\n            return (false, result);\\n        }\\n        for (uint256 i = 2; i < digestInfoStart - 1; i++) {\\n            if (result[i] != 0xFF) {\\n                return (false, result);\\n            }\\n        }\\n\\n        return (true, result);\\n    }\\n}\\n\",\"keccak256\":\"0x92c872f6bb94670de46829d61122fcb0b0642dbd8e0e6fe31d2e8d387c890e87\"},\"project/contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"./RSAPKCS1Verify.sol\\\";\\nimport \\\"../../utils/BytesUtils.sol\\\";\\n\\n/// @dev Implements the DNSSEC RSASHA256 algorithm.\\ncontract RSASHA256Algorithm is Algorithm {\\n    using BytesUtils for *;\\n\\n    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata sig\\n    ) external view override returns (bool) {\\n        bytes memory exponent;\\n        bytes memory modulus;\\n\\n        uint16 exponentLen = uint16(key.readUint8(4));\\n        if (exponentLen != 0) {\\n            exponent = key.substring(5, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 5,\\n                key.length - exponentLen - 5\\n            );\\n        } else {\\n            exponentLen = key.readUint16(5);\\n            exponent = key.substring(7, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 7,\\n                key.length - exponentLen - 7\\n            );\\n        }\\n\\n        return RSAPKCS1Verify.verifySHA256(modulus, exponent, sig, sha256(data));\\n    }\\n}\\n\",\"keccak256\":\"0x7fcee47279521f12f45867173e778ccf575f3af26d880132927897bb1b12889e\"},\"project/contracts/dnssec-oracle/algorithms/RSAVerify.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./ModexpPrecompile.sol\\\";\\nimport \\\"../../utils/BytesUtils.sol\\\";\\n\\nlibrary RSAVerify {\\n    /// @dev Recovers the input data from an RSA signature, returning the result in S.\\n    /// @param N The RSA public modulus.\\n    /// @param E The RSA public exponent.\\n    /// @param S The signature to recover.\\n    /// @return True if the recovery succeeded.\\n    function rsarecover(\\n        bytes memory N,\\n        bytes memory E,\\n        bytes memory S\\n    ) internal view returns (bool, bytes memory) {\\n        return ModexpPrecompile.modexp(S, E, N);\\n    }\\n}\\n\",\"keccak256\":\"0x3de747c1a48c82031e79a35c6b844697e48c8d0549cb3475783b1447895ef8ab\"},\"project/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n    /// @dev `offset` was beyond `length`.\\n    ///       Error selector: `0x8a3c1cfb`\\n    error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n    /// @dev Assert `end` is not beyond the length of `v`.\\n    function _checkBound(bytes memory v, uint256 end) internal pure {\\n        if (end > v.length) {\\n            revert OffsetOutOfBoundsError(end, v.length);\\n        }\\n    }\\n\\n    /// @dev Compute `keccak256(v[off:off+len])`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @param len The number of bytes to hash.\\n    /// @return ret The corresponding hash.\\n    function keccak(\\n        bytes memory v,\\n        uint256 off,\\n        uint256 len\\n    ) internal pure returns (bytes32 ret) {\\n        _checkBound(v, off + len);\\n        assembly (\\\"memory-safe\\\") {\\n            ret := keccak256(add(add(v, 32), off), len)\\n        }\\n    }\\n\\n    /// @dev Lexicographically compare two byte strings.\\n    /// @param vA The first bytes to compare.\\n    /// @param vB The second bytes to compare.\\n    /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n    function compare(\\n        bytes memory vA,\\n        bytes memory vB\\n    ) internal pure returns (int256) {\\n        return compare(vA, 0, vA.length, vB, 0, vB.length);\\n    }\\n\\n    /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n    /// @param vA The first bytes.\\n    /// @param offA The offset of the first bytes.\\n    /// @param lenA The length of the first bytes.\\n    /// @param vB The second bytes.\\n    /// @param offB The offset of the second bytes.\\n    /// @param lenB The length of the second bytes.\\n    /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n    function compare(\\n        bytes memory vA,\\n        uint256 offA,\\n        uint256 lenA,\\n        bytes memory vB,\\n        uint256 offB,\\n        uint256 lenB\\n    ) internal pure returns (int256) {\\n        _checkBound(vA, offA + lenA);\\n        _checkBound(vB, offB + lenB);\\n        unchecked {\\n            uint256 ptrA = LibMem.ptr(vA) + offA;\\n            uint256 ptrB = LibMem.ptr(vB) + offB;\\n            uint256 shortest = lenA < lenB ? lenA : lenB;\\n            for (uint256 i; i < shortest; i += 32) {\\n                uint256 a = LibMem.load(ptrA + i);\\n                uint256 b = LibMem.load(ptrB + i);\\n                if (a != b) {\\n                    uint256 rest = shortest - i;\\n                    if (rest < 32) {\\n                        rest = (32 - rest) << 3; // bits to drop\\n                        a >>= rest; // shift out the\\n                        b >>= rest; // irrelevant bits\\n                    }\\n                    if (a < b) {\\n                        return -1;\\n                    } else if (a > b) {\\n                        return 1;\\n                    }\\n                }\\n            }\\n        }\\n        return int256(lenA) - int256(lenB);\\n    }\\n\\n    /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n    /// @param vA The first bytes.\\n    /// @param offA The offset into the first bytes.\\n    /// @param vB The second bytes.\\n    /// @param offB The offset into the second bytes.\\n    /// @param len The number of bytes to compare.\\n    /// @return True if the byte ranges are equal.\\n    function equals(\\n        bytes memory vA,\\n        uint256 offA,\\n        bytes memory vB,\\n        uint256 offB,\\n        uint256 len\\n    ) internal pure returns (bool) {\\n        return keccak(vA, offA, len) == keccak(vB, offB, len);\\n    }\\n\\n    /// @dev Determine if `a[offA:] == b[offB:]`.\\n    /// @param vA The first bytes.\\n    /// @param offA The offset into the first bytes.\\n    /// @param vB The second bytes.\\n    /// @param offB The offset into the second bytes.\\n    /// @return True if the byte ranges are equal.\\n    function equals(\\n        bytes memory vA,\\n        uint256 offA,\\n        bytes memory vB,\\n        uint256 offB\\n    ) internal pure returns (bool) {\\n        _checkBound(vA, offA);\\n        _checkBound(vB, offB);\\n        unchecked {\\n            return\\n                keccak(vA, offA, vA.length - offA) ==\\n                keccak(vB, offB, vB.length - offB);\\n        }\\n    }\\n\\n    /// @dev Determine if `a[offA:] == b`.\\n    /// @param vA The first bytes.\\n    /// @param offA The offset into the first bytes.\\n    /// @param vB The second bytes.\\n    /// @return True if the byte ranges are equal.\\n    function equals(\\n        bytes memory vA,\\n        uint256 offA,\\n        bytes memory vB\\n    ) internal pure returns (bool) {\\n        return\\n            vA.length == offA + vB.length &&\\n            keccak(vA, offA, vB.length) == keccak256(vB);\\n    }\\n\\n    /// @dev Determine if `a == b`.\\n    /// @param vA The first bytes.\\n    /// @param vB The second bytes.\\n    /// @return True if the bytes are equal.\\n    function equals(\\n        bytes memory vA,\\n        bytes memory vB\\n    ) internal pure returns (bool) {\\n        return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n    }\\n\\n    /// @dev Returns `uint8(v[off])`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @return The corresponding `uint8`.\\n    function readUint8(\\n        bytes memory v,\\n        uint256 off\\n    ) internal pure returns (uint8) {\\n        _checkBound(v, off + 1);\\n        unchecked {\\n            return uint8(v[off]);\\n        }\\n    }\\n\\n    /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @return ret The corresponding `uint16`.\\n    function readUint16(\\n        bytes memory v,\\n        uint256 off\\n    ) internal pure returns (uint16 ret) {\\n        _checkBound(v, off + 2);\\n        assembly (\\\"memory-safe\\\") {\\n            ret := shr(240, mload(add(add(v, 32), off)))\\n        }\\n    }\\n\\n    /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @return ret The corresponding `uint32`.\\n    function readUint32(\\n        bytes memory v,\\n        uint256 off\\n    ) internal pure returns (uint32 ret) {\\n        _checkBound(v, off + 4);\\n        assembly (\\\"memory-safe\\\") {\\n            ret := shr(224, mload(add(add(v, 32), off)))\\n        }\\n    }\\n\\n    /// @dev Returns `bytes20(v[off:off+20])`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @return ret The corresponding `bytes20`.\\n    function readBytes20(\\n        bytes memory v,\\n        uint256 off\\n    ) internal pure returns (bytes20 ret) {\\n        _checkBound(v, off + 20);\\n        assembly (\\\"memory-safe\\\") {\\n            ret := shl(96, mload(add(add(v, 20), off)))\\n        }\\n    }\\n\\n    /// @dev Returns `bytes32(v[off:off+32])`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @return ret The corresponding `bytes32`.\\n    function readBytes32(\\n        bytes memory v,\\n        uint256 off\\n    ) internal pure returns (bytes32 ret) {\\n        _checkBound(v, off + 32);\\n        assembly (\\\"memory-safe\\\") {\\n            ret := mload(add(add(v, 32), off))\\n        }\\n    }\\n\\n    /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n    ///      Accepts 0-32 bytes or reverts.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @param len The number of bytes.\\n    /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n    function readBytesN(\\n        bytes memory v,\\n        uint256 off,\\n        uint256 len\\n    ) internal pure returns (bytes32 ret) {\\n        assert(len <= 32);\\n        _checkBound(v, off + len);\\n        assembly (\\\"memory-safe\\\") {\\n            let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00><NxFF>\\n            ret := and(mload(add(add(v, 32), off)), not(mask))\\n        }\\n    }\\n\\n    /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n    /// @param vSrc The source bytes.\\n    /// @param offSrc The offset into the source to begin the copy.\\n    /// @param vDst The destination bytes.\\n    /// @param offDst The offset into the destination to place the copy.\\n    /// @param len The number of bytes to copy.\\n    function copyBytes(\\n        bytes memory vSrc,\\n        uint256 offSrc,\\n        bytes memory vDst,\\n        uint256 offDst,\\n        uint256 len\\n    ) internal pure {\\n        _checkBound(vSrc, offSrc + len);\\n        _checkBound(vDst, offDst + len);\\n        unchecked {\\n            LibMem.copy(\\n                LibMem.ptr(vDst) + offDst,\\n                LibMem.ptr(vSrc) + offSrc,\\n                len\\n            );\\n        }\\n    }\\n\\n    /// @dev Copies a substring into a new byte string.\\n    /// @param vSrc The byte string to copy from.\\n    /// @param off The offset to start copying at.\\n    /// @param len The number of bytes to copy.\\n    /// @return vDst The copied substring.\\n    function substring(\\n        bytes memory vSrc,\\n        uint256 off,\\n        uint256 len\\n    ) internal pure returns (bytes memory vDst) {\\n        vDst = new bytes(len);\\n        copyBytes(vSrc, off, vDst, 0, len);\\n    }\\n\\n    /// @dev Find the first occurrence of `needle`.\\n    /// @param v The bytes to search.\\n    /// @param off The offset to start searching.\\n    /// @param len The number of bytes to search.\\n    /// @param needle The byte to search for.\\n    /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n    function find(\\n        bytes memory v,\\n        uint256 off,\\n        uint256 len,\\n        bytes1 needle\\n    ) internal pure returns (uint256) {\\n        for (uint256 end = off + len; off < end; off++) {\\n            if (v[off] == needle) {\\n                return off;\\n            }\\n        }\\n        return type(uint256).max;\\n    }\\n\\n    /// @dev Returns `true` if word contains a zero byte.\\n    function hasZeroByte(uint256 word) internal pure returns (bool) {\\n        unchecked {\\n            return\\n                ((~word &\\n                    (word -\\n                        0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n                    0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n                0;\\n        }\\n    }\\n\\n    /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @param len The number of bytes to search.\\n    /// @param needle The byte to search for.\\n    /// @return found `true` if `needle` was found.\\n    function includes(\\n        bytes memory v,\\n        uint256 off,\\n        uint256 len,\\n        bytes1 needle\\n    ) internal pure returns (bool found) {\\n        _checkBound(v, off + len);\\n        unchecked {\\n            uint256 wide = uint8(needle);\\n            wide |= wide << 8;\\n            wide |= wide << 16;\\n            wide |= wide << 32;\\n            wide |= wide << 64;\\n            wide |= wide << 128; // broadcast byte across word\\n            off += LibMem.ptr(v);\\n            len += off;\\n            while (off < len) {\\n                uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n                off += 32;\\n                if (hasZeroByte(word)) {\\n                    return\\n                        off <= len ||\\n                        hasZeroByte(\\n                            word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n                        );\\n                }\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n    /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n    ///      Equivalent to `mcopy()`.\\n    ///\\n    /// @param src The source memory offset.\\n    /// @param dst The destination memory offset.\\n    /// @param len The number of bytes to copy.\\n    function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n        assembly {\\n            // Copy word-length chunks while possible\\n            // prettier-ignore\\n            for {} gt(len, 31) {} {\\n                mstore(dst, mload(src))\\n                dst := add(dst, 32)\\n                src := add(src, 32)\\n                len := sub(len, 32)\\n            }\\n            // Copy remaining bytes\\n            if len {\\n                let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n                let wSrc := and(mload(src), not(mask))\\n                let wDst := and(mload(dst), mask)\\n                mstore(dst, or(wSrc, wDst))\\n            }\\n        }\\n    }\\n\\n    /// @dev Convert bytes to a memory offset.\\n    ///\\n    /// @param v The bytes to convert.\\n    ///\\n    /// @return ret The corresponding memory offset.\\n    function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n        assembly {\\n            ret := add(v, 32)\\n        }\\n    }\\n\\n    /// @dev Read word at memory offset.\\n    ///\\n    /// @param src The memory offset.\\n    ///\\n    /// @return ret The read word.\\n    function load(uint256 src) internal pure returns (uint256 ret) {\\n        assembly {\\n            ret := mload(src)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"}},\"version\":1}",
    +  "storageLayout": {
    +    "storage": [],
    +    "types": null
    +  },
       "userdoc": {
         "kind": "user",
         "methods": {},
         "version": 1
       },
    -  "storageLayout": {
    -    "storage": [],
    -    "types": null
    +  "argsData": "0x",
    +  "transaction": {
    +    "hash": "0x5d663405adc50bd10a4af5becba7566c44ade9223a01cb7daf92af45656ce678",
    +    "nonce": "0x1",
    +    "origin": "0x4e472d50f3d735e76a143afcadae7f03db6995de"
    +  },
    +  "receipt": {
    +    "blockHash": "0xe81b997aaf1faff770811945554e2ee45615db96fca0c1cf3f933e3492181015",
    +    "blockNumber": "0x1763f18",
    +    "transactionIndex": "0x2b"
       }
     }
    \ No newline at end of file
    
  • deployments/sepolia/.chain+1 0 added
    @@ -0,0 +1 @@
    +{"chainId":"11155111","genesisHash":"0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9"}
    \ No newline at end of file
    
  • deployments/sepolia/.chainId+0 1 removed
    @@ -1 +0,0 @@
    -11155111
    \ No newline at end of file
    
  • deployments/sepolia/DummyAlgorithm.json+36 26 modified
    @@ -1,5 +1,5 @@
     {
    -  "address": "0x9f71e0eb3DdaD8187638ba5893Df04a87b463329",
    +  "address": "0x2c21146873b5bce5b9a8a441124e01981d95a831",
       "abi": [
         {
           "inputs": [
    @@ -31,41 +31,51 @@
           "type": "function"
         }
       ],
    -  "transactionHash": "0x42f391e4991f7d2a2a3aaae45c6700a74856845ea383aa03bc139e0d0ce9d397",
    -  "receipt": {
    -    "to": null,
    -    "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8",
    -    "contractAddress": "0x9f71e0eb3DdaD8187638ba5893Df04a87b463329",
    -    "transactionIndex": 125,
    -    "gasUsed": "134217",
    -    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    -    "blockHash": "0x2c10cef6db1a05e518f5031fc3323469beb0b07d68a737f5da0f50cf5d324f8e",
    -    "transactionHash": "0x42f391e4991f7d2a2a3aaae45c6700a74856845ea383aa03bc139e0d0ce9d397",
    -    "logs": [],
    -    "blockNumber": 4141618,
    -    "cumulativeGasUsed": "12587290",
    -    "status": 1,
    -    "byzantium": true
    -  },
    -  "args": [],
    -  "numDeployments": 1,
    -  "solcInputHash": "e04502f562d98d0455f6c1c453418cdd",
    -  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements a dummy DNSSEC (signing) algorithm that approves all      signatures, for testing.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/algorithms/DummyAlgorithm.sol\":\"DummyAlgorithm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"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/algorithms/DummyAlgorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\n\\n/**\\n * @dev Implements a dummy DNSSEC (signing) algorithm that approves all\\n *      signatures, for testing.\\n */\\ncontract DummyAlgorithm is Algorithm {\\n    function verify(\\n        bytes calldata,\\n        bytes calldata,\\n        bytes calldata\\n    ) external view override returns (bool) {\\n        return true;\\n    }\\n}\\n\",\"keccak256\":\"0x0df474d4178b1659d2869aefe90ee6680b966d9432c5b28ef388134ea6d67b58\"}},\"version\":1}",
    -  "bytecode": "0x608060405234801561001057600080fd5b50610177806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004a61003e3660046100a7565b60019695505050505050565b604051901515815260200160405180910390f35b60008083601f84011261007057600080fd5b50813567ffffffffffffffff81111561008857600080fd5b6020830191508360208285010111156100a057600080fd5b9250929050565b600080600080600080606087890312156100c057600080fd5b863567ffffffffffffffff808211156100d857600080fd5b6100e48a838b0161005e565b909850965060208901359150808211156100fd57600080fd5b6101098a838b0161005e565b9096509450604089013591508082111561012257600080fd5b5061012f89828a0161005e565b979a969950949750929593949250505056fea26469706673582212201d6169f54d5644e6220fe6e528677b0fc01f94f6ab546738c10ff226848cce1b64736f6c63430008110033",
    -  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004a61003e3660046100a7565b60019695505050505050565b604051901515815260200160405180910390f35b60008083601f84011261007057600080fd5b50813567ffffffffffffffff81111561008857600080fd5b6020830191508360208285010111156100a057600080fd5b9250929050565b600080600080600080606087890312156100c057600080fd5b863567ffffffffffffffff808211156100d857600080fd5b6100e48a838b0161005e565b909850965060208901359150808211156100fd57600080fd5b6101098a838b0161005e565b9096509450604089013591508082111561012257600080fd5b5061012f89828a0161005e565b979a969950949750929593949250505056fea26469706673582212201d6169f54d5644e6220fe6e528677b0fc01f94f6ab546738c10ff226848cce1b64736f6c63430008110033",
    +  "contractName": "DummyAlgorithm",
    +  "sourceName": "contracts/dnssec-oracle/algorithms/DummyAlgorithm.sol",
    +  "bytecode": "0x6080604052348015600f57600080fd5b506101838061001f6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004a61003e3660046100a7565b60019695505050505050565b604051901515815260200160405180910390f35b60008083601f84011261007057600080fd5b50813567ffffffffffffffff81111561008857600080fd5b6020830191508360208285010111156100a057600080fd5b9250929050565b600080600080600080606087890312156100c057600080fd5b863567ffffffffffffffff8111156100d757600080fd5b6100e389828a0161005e565b909750955050602087013567ffffffffffffffff81111561010357600080fd5b61010f89828a0161005e565b909550935050604087013567ffffffffffffffff81111561012f57600080fd5b61013b89828a0161005e565b979a969950949750929593949250505056fea2646970667358221220b58a9cbb4d9cff1d67ba2416b847c53d6ee00337fa7d09ef2d0559eb22a5b02164736f6c634300081a0033",
    +  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004a61003e3660046100a7565b60019695505050505050565b604051901515815260200160405180910390f35b60008083601f84011261007057600080fd5b50813567ffffffffffffffff81111561008857600080fd5b6020830191508360208285010111156100a057600080fd5b9250929050565b600080600080600080606087890312156100c057600080fd5b863567ffffffffffffffff8111156100d757600080fd5b6100e389828a0161005e565b909750955050602087013567ffffffffffffffff81111561010357600080fd5b61010f89828a0161005e565b909550935050604087013567ffffffffffffffff81111561012f57600080fd5b61013b89828a0161005e565b979a969950949750929593949250505056fea2646970667358221220b58a9cbb4d9cff1d67ba2416b847c53d6ee00337fa7d09ef2d0559eb22a5b02164736f6c634300081a0033",
    +  "linkReferences": {},
    +  "deployedLinkReferences": {},
    +  "immutableReferences": {},
    +  "inputSourceName": "project/contracts/dnssec-oracle/algorithms/DummyAlgorithm.sol",
       "devdoc": {
         "details": "Implements a dummy DNSSEC (signing) algorithm that approves all      signatures, for testing.",
         "kind": "dev",
         "methods": {},
         "version": 1
       },
    +  "evm": {
    +    "gasEstimates": {
    +      "creation": {
    +        "codeDepositCost": "77400",
    +        "executionCost": "129",
    +        "totalCost": "77529"
    +      },
    +      "external": {
    +        "verify(bytes,bytes,bytes)": "infinite"
    +      }
    +    }
    +  },
    +  "metadata": "{\"compiler\":{\"version\":\"0.8.26+commit.8a97fa7a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements a dummy DNSSEC (signing) algorithm that approves all      signatures, for testing.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/contracts/dnssec-oracle/algorithms/DummyAlgorithm.sol\":\"DummyAlgorithm\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[\"project/:@ensdomains/buffer/=npm/@ensdomains/buffer@0.1.3/\",\"project/:@ensdomains/solsha1/=npm/@ensdomains/solsha1@0.0.3/\",\"project/:@openzeppelin/contracts-v5/=npm/@openzeppelin/contracts@5.1.0/\",\"project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@4.9.3/\",\"project/:@unruggable/gateways/=npm/@unruggable/gateways@1.3.0/contracts/\"]},\"sources\":{\"project/contracts/dnssec-oracle/algorithms/Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/// @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\\ninterface Algorithm {\\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    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xbcbdc06d72b64903e733e7ddfbf59c35c984c3eb0022baacab12c97292cc13df\"},\"project/contracts/dnssec-oracle/algorithms/DummyAlgorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\n\\n/// @dev Implements a dummy DNSSEC (signing) algorithm that approves all\\n///      signatures, for testing.\\ncontract DummyAlgorithm is Algorithm {\\n    function verify(\\n        bytes calldata,\\n        bytes calldata,\\n        bytes calldata\\n    ) external view override returns (bool) {\\n        return true;\\n    }\\n}\\n\",\"keccak256\":\"0x90bd156a2352bfabcd2f0e77cd406103168a48e56bd76e24cead7cbe6c41ed80\"}},\"version\":1}",
    +  "storageLayout": {
    +    "storage": [],
    +    "types": null
    +  },
       "userdoc": {
         "kind": "user",
         "methods": {},
         "version": 1
       },
    -  "storageLayout": {
    -    "storage": [],
    -    "types": null
    +  "argsData": "0x",
    +  "transaction": {
    +    "hash": "0x83053f3e0dea17c6220d8254f4e31d7707dc296a01f2ad23f6deb0c0966c7182",
    +    "nonce": "0xa",
    +    "origin": "0xceed1f4f358e635da87704305c884b4550e82ecb"
    +  },
    +  "receipt": {
    +    "blockHash": "0xe1201fbb6fc707e2bef72bfa4093b1feb9dd5826594b789e88b06b38fc74cd2d",
    +    "blockNumber": "0x9dacb3",
    +    "transactionIndex": "0x7"
       }
     }
    \ No newline at end of file
    
  • deployments/sepolia/P256SHA256Algorithm.json+42 29 modified
    @@ -1,5 +1,5 @@
     {
    -  "address": "0x5C4Eb1af37a535A8E733Df47a291aAC6fC80E497",
    +  "address": "0x034262be25dc0e304e04e111f2a6bf1dbf1e260f",
       "abi": [
         {
           "inputs": [
    @@ -31,52 +31,65 @@
           "type": "function"
         }
       ],
    -  "transactionHash": "0xadc9be7cf7a7d455269dc5b215bc8e6d46e109972666f892a11fe0ee9f0ad0cd",
    -  "receipt": {
    -    "to": null,
    -    "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8",
    -    "contractAddress": "0x5C4Eb1af37a535A8E733Df47a291aAC6fC80E497",
    -    "transactionIndex": 59,
    -    "gasUsed": "896222",
    -    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    -    "blockHash": "0x503455574876450ba13901830b82805a51ac49e5c70a32596408536ddaf20079",
    -    "transactionHash": "0xadc9be7cf7a7d455269dc5b215bc8e6d46e109972666f892a11fe0ee9f0ad0cd",
    -    "logs": [],
    -    "blockNumber": 4141617,
    -    "cumulativeGasUsed": "11666046",
    -    "status": 1,
    -    "byzantium": true
    -  },
    -  "args": [],
    -  "numDeployments": 1,
    -  "solcInputHash": "e04502f562d98d0455f6c1c453418cdd",
    -  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"verify(bytes,bytes,bytes)\":{\"details\":\"Verifies a signature.\",\"params\":{\"data\":\"The signed data to verify.\",\"key\":\"The public key to verify with.\",\"signature\":\"The signature to verify.\"},\"returns\":{\"_0\":\"True iff the signature is valid.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol\":\"P256SHA256Algorithm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"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/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/algorithms/EllipticCurve.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @title   EllipticCurve\\n *\\n * @author  Tilman Drerup;\\n *\\n * @notice  Implements elliptic curve math; Parametrized for SECP256R1.\\n *\\n *          Includes components of code by Andreas Olofsson, Alexander Vlasov\\n *          (https://github.com/BANKEX/CurveArithmetics), and Avi Asayag\\n *          (https://github.com/orbs-network/elliptic-curve-solidity)\\n *\\n *          Source: https://github.com/tdrerup/elliptic-curve-solidity\\n *\\n * @dev     NOTE: To disambiguate public keys when verifying signatures, activate\\n *          condition 'rs[1] > lowSmax' in validateSignature().\\n */\\ncontract EllipticCurve {\\n    // Set parameters for curve.\\n    uint256 constant a =\\n        0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\\n    uint256 constant b =\\n        0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\\n    uint256 constant gx =\\n        0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\\n    uint256 constant gy =\\n        0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\\n    uint256 constant p =\\n        0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n    uint256 constant n =\\n        0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\\n\\n    uint256 constant lowSmax =\\n        0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0;\\n\\n    /**\\n     * @dev Inverse of u in the field of modulo m.\\n     */\\n    function inverseMod(uint256 u, uint256 m) internal pure returns (uint256) {\\n        unchecked {\\n            if (u == 0 || u == m || m == 0) return 0;\\n            if (u > m) u = u % m;\\n\\n            int256 t1;\\n            int256 t2 = 1;\\n            uint256 r1 = m;\\n            uint256 r2 = u;\\n            uint256 q;\\n\\n            while (r2 != 0) {\\n                q = r1 / r2;\\n                (t1, t2, r1, r2) = (t2, t1 - int256(q) * t2, r2, r1 - q * r2);\\n            }\\n\\n            if (t1 < 0) return (m - uint256(-t1));\\n\\n            return uint256(t1);\\n        }\\n    }\\n\\n    /**\\n     * @dev Transform affine coordinates into projective coordinates.\\n     */\\n    function toProjectivePoint(\\n        uint256 x0,\\n        uint256 y0\\n    ) internal pure returns (uint256[3] memory P) {\\n        P[2] = addmod(0, 1, p);\\n        P[0] = mulmod(x0, P[2], p);\\n        P[1] = mulmod(y0, P[2], p);\\n    }\\n\\n    /**\\n     * @dev Add two points in affine coordinates and return projective point.\\n     */\\n    function addAndReturnProjectivePoint(\\n        uint256 x1,\\n        uint256 y1,\\n        uint256 x2,\\n        uint256 y2\\n    ) internal pure returns (uint256[3] memory P) {\\n        uint256 x;\\n        uint256 y;\\n        (x, y) = add(x1, y1, x2, y2);\\n        P = toProjectivePoint(x, y);\\n    }\\n\\n    /**\\n     * @dev Transform from projective to affine coordinates.\\n     */\\n    function toAffinePoint(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 z0\\n    ) internal pure returns (uint256 x1, uint256 y1) {\\n        uint256 z0Inv;\\n        z0Inv = inverseMod(z0, p);\\n        x1 = mulmod(x0, z0Inv, p);\\n        y1 = mulmod(y0, z0Inv, p);\\n    }\\n\\n    /**\\n     * @dev Return the zero curve in projective coordinates.\\n     */\\n    function zeroProj()\\n        internal\\n        pure\\n        returns (uint256 x, uint256 y, uint256 z)\\n    {\\n        return (0, 1, 0);\\n    }\\n\\n    /**\\n     * @dev Return the zero curve in affine coordinates.\\n     */\\n    function zeroAffine() internal pure returns (uint256 x, uint256 y) {\\n        return (0, 0);\\n    }\\n\\n    /**\\n     * @dev Check if the curve is the zero curve.\\n     */\\n    function isZeroCurve(\\n        uint256 x0,\\n        uint256 y0\\n    ) internal pure returns (bool isZero) {\\n        if (x0 == 0 && y0 == 0) {\\n            return true;\\n        }\\n        return false;\\n    }\\n\\n    /**\\n     * @dev Check if a point in affine coordinates is on the curve.\\n     */\\n    function isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\\n        if (0 == x || x == p || 0 == y || y == p) {\\n            return false;\\n        }\\n\\n        uint256 LHS = mulmod(y, y, p); // y^2\\n        uint256 RHS = mulmod(mulmod(x, x, p), x, p); // x^3\\n\\n        if (a != 0) {\\n            RHS = addmod(RHS, mulmod(x, a, p), p); // x^3 + a*x\\n        }\\n        if (b != 0) {\\n            RHS = addmod(RHS, b, p); // x^3 + a*x + b\\n        }\\n\\n        return LHS == RHS;\\n    }\\n\\n    /**\\n     * @dev Double an elliptic curve point in projective coordinates. See\\n     * https://www.nayuki.io/page/elliptic-curve-point-addition-in-projective-coordinates\\n     */\\n    function twiceProj(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 z0\\n    ) internal pure returns (uint256 x1, uint256 y1, uint256 z1) {\\n        uint256 t;\\n        uint256 u;\\n        uint256 v;\\n        uint256 w;\\n\\n        if (isZeroCurve(x0, y0)) {\\n            return zeroProj();\\n        }\\n\\n        u = mulmod(y0, z0, p);\\n        u = mulmod(u, 2, p);\\n\\n        v = mulmod(u, x0, p);\\n        v = mulmod(v, y0, p);\\n        v = mulmod(v, 2, p);\\n\\n        x0 = mulmod(x0, x0, p);\\n        t = mulmod(x0, 3, p);\\n\\n        z0 = mulmod(z0, z0, p);\\n        z0 = mulmod(z0, a, p);\\n        t = addmod(t, z0, p);\\n\\n        w = mulmod(t, t, p);\\n        x0 = mulmod(2, v, p);\\n        w = addmod(w, p - x0, p);\\n\\n        x0 = addmod(v, p - w, p);\\n        x0 = mulmod(t, x0, p);\\n        y0 = mulmod(y0, u, p);\\n        y0 = mulmod(y0, y0, p);\\n        y0 = mulmod(2, y0, p);\\n        y1 = addmod(x0, p - y0, p);\\n\\n        x1 = mulmod(u, w, p);\\n\\n        z1 = mulmod(u, u, p);\\n        z1 = mulmod(z1, u, p);\\n    }\\n\\n    /**\\n     * @dev Add two elliptic curve points in projective coordinates. See\\n     * https://www.nayuki.io/page/elliptic-curve-point-addition-in-projective-coordinates\\n     */\\n    function addProj(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 z0,\\n        uint256 x1,\\n        uint256 y1,\\n        uint256 z1\\n    ) internal pure returns (uint256 x2, uint256 y2, uint256 z2) {\\n        uint256 t0;\\n        uint256 t1;\\n        uint256 u0;\\n        uint256 u1;\\n\\n        if (isZeroCurve(x0, y0)) {\\n            return (x1, y1, z1);\\n        } else if (isZeroCurve(x1, y1)) {\\n            return (x0, y0, z0);\\n        }\\n\\n        t0 = mulmod(y0, z1, p);\\n        t1 = mulmod(y1, z0, p);\\n\\n        u0 = mulmod(x0, z1, p);\\n        u1 = mulmod(x1, z0, p);\\n\\n        if (u0 == u1) {\\n            if (t0 == t1) {\\n                return twiceProj(x0, y0, z0);\\n            } else {\\n                return zeroProj();\\n            }\\n        }\\n\\n        (x2, y2, z2) = addProj2(mulmod(z0, z1, p), u0, u1, t1, t0);\\n    }\\n\\n    /**\\n     * @dev Helper function that splits addProj to avoid too many local variables.\\n     */\\n    function addProj2(\\n        uint256 v,\\n        uint256 u0,\\n        uint256 u1,\\n        uint256 t1,\\n        uint256 t0\\n    ) private pure returns (uint256 x2, uint256 y2, uint256 z2) {\\n        uint256 u;\\n        uint256 u2;\\n        uint256 u3;\\n        uint256 w;\\n        uint256 t;\\n\\n        t = addmod(t0, p - t1, p);\\n        u = addmod(u0, p - u1, p);\\n        u2 = mulmod(u, u, p);\\n\\n        w = mulmod(t, t, p);\\n        w = mulmod(w, v, p);\\n        u1 = addmod(u1, u0, p);\\n        u1 = mulmod(u1, u2, p);\\n        w = addmod(w, p - u1, p);\\n\\n        x2 = mulmod(u, w, p);\\n\\n        u3 = mulmod(u2, u, p);\\n        u0 = mulmod(u0, u2, p);\\n        u0 = addmod(u0, p - w, p);\\n        t = mulmod(t, u0, p);\\n        t0 = mulmod(t0, u3, p);\\n\\n        y2 = addmod(t, p - t0, p);\\n\\n        z2 = mulmod(u3, v, p);\\n    }\\n\\n    /**\\n     * @dev Add two elliptic curve points in affine coordinates.\\n     */\\n    function add(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 x1,\\n        uint256 y1\\n    ) internal pure returns (uint256, uint256) {\\n        uint256 z0;\\n\\n        (x0, y0, z0) = addProj(x0, y0, 1, x1, y1, 1);\\n\\n        return toAffinePoint(x0, y0, z0);\\n    }\\n\\n    /**\\n     * @dev Double an elliptic curve point in affine coordinates.\\n     */\\n    function twice(\\n        uint256 x0,\\n        uint256 y0\\n    ) internal pure returns (uint256, uint256) {\\n        uint256 z0;\\n\\n        (x0, y0, z0) = twiceProj(x0, y0, 1);\\n\\n        return toAffinePoint(x0, y0, z0);\\n    }\\n\\n    /**\\n     * @dev Multiply an elliptic curve point by a 2 power base (i.e., (2^exp)*P)).\\n     */\\n    function multiplyPowerBase2(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 exp\\n    ) internal pure returns (uint256, uint256) {\\n        uint256 base2X = x0;\\n        uint256 base2Y = y0;\\n        uint256 base2Z = 1;\\n\\n        for (uint256 i = 0; i < exp; i++) {\\n            (base2X, base2Y, base2Z) = twiceProj(base2X, base2Y, base2Z);\\n        }\\n\\n        return toAffinePoint(base2X, base2Y, base2Z);\\n    }\\n\\n    /**\\n     * @dev Multiply an elliptic curve point by a scalar.\\n     */\\n    function multiplyScalar(\\n        uint256 x0,\\n        uint256 y0,\\n        uint256 scalar\\n    ) internal pure returns (uint256 x1, uint256 y1) {\\n        if (scalar == 0) {\\n            return zeroAffine();\\n        } else if (scalar == 1) {\\n            return (x0, y0);\\n        } else if (scalar == 2) {\\n            return twice(x0, y0);\\n        }\\n\\n        uint256 base2X = x0;\\n        uint256 base2Y = y0;\\n        uint256 base2Z = 1;\\n        uint256 z1 = 1;\\n        x1 = x0;\\n        y1 = y0;\\n\\n        if (scalar % 2 == 0) {\\n            x1 = y1 = 0;\\n        }\\n\\n        scalar = scalar >> 1;\\n\\n        while (scalar > 0) {\\n            (base2X, base2Y, base2Z) = twiceProj(base2X, base2Y, base2Z);\\n\\n            if (scalar % 2 == 1) {\\n                (x1, y1, z1) = addProj(base2X, base2Y, base2Z, x1, y1, z1);\\n            }\\n\\n            scalar = scalar >> 1;\\n        }\\n\\n        return toAffinePoint(x1, y1, z1);\\n    }\\n\\n    /**\\n     * @dev Multiply the curve's generator point by a scalar.\\n     */\\n    function multipleGeneratorByScalar(\\n        uint256 scalar\\n    ) internal pure returns (uint256, uint256) {\\n        return multiplyScalar(gx, gy, scalar);\\n    }\\n\\n    /**\\n     * @dev Validate combination of message, signature, and public key.\\n     */\\n    function validateSignature(\\n        bytes32 message,\\n        uint256[2] memory rs,\\n        uint256[2] memory Q\\n    ) internal pure returns (bool) {\\n        // To disambiguate between public key solutions, include comment below.\\n        if (rs[0] == 0 || rs[0] >= n || rs[1] == 0) {\\n            // || rs[1] > lowSmax)\\n            return false;\\n        }\\n        if (!isOnCurve(Q[0], Q[1])) {\\n            return false;\\n        }\\n\\n        uint256 x1;\\n        uint256 x2;\\n        uint256 y1;\\n        uint256 y2;\\n\\n        uint256 sInv = inverseMod(rs[1], n);\\n        (x1, y1) = multiplyScalar(gx, gy, mulmod(uint256(message), sInv, n));\\n        (x2, y2) = multiplyScalar(Q[0], Q[1], mulmod(rs[0], sInv, n));\\n        uint256[3] memory P = addAndReturnProjectivePoint(x1, y1, x2, y2);\\n\\n        if (P[2] == 0) {\\n            return false;\\n        }\\n\\n        uint256 Px = inverseMod(P[2], p);\\n        Px = mulmod(P[0], mulmod(Px, Px, p), p);\\n\\n        return Px % n == rs[0];\\n    }\\n}\\n\",\"keccak256\":\"0xdee968ffbfcb9a05b7ed7845e2c55f438f5e09a80fc6024c751a1718137e1838\"},\"contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"./EllipticCurve.sol\\\";\\nimport \\\"../BytesUtils.sol\\\";\\n\\ncontract P256SHA256Algorithm is Algorithm, EllipticCurve {\\n    using BytesUtils for *;\\n\\n    /**\\n     * @dev Verifies a signature.\\n     * @param key The public key to verify with.\\n     * @param data The signed data to verify.\\n     * @param signature The signature to verify.\\n     * @return True iff the signature is valid.\\n     */\\n    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view override returns (bool) {\\n        return\\n            validateSignature(\\n                sha256(data),\\n                parseSignature(signature),\\n                parseKey(key)\\n            );\\n    }\\n\\n    function parseSignature(\\n        bytes memory data\\n    ) internal pure returns (uint256[2] memory) {\\n        require(data.length == 64, \\\"Invalid p256 signature length\\\");\\n        return [uint256(data.readBytes32(0)), uint256(data.readBytes32(32))];\\n    }\\n\\n    function parseKey(\\n        bytes memory data\\n    ) internal pure returns (uint256[2] memory) {\\n        require(data.length == 68, \\\"Invalid p256 key length\\\");\\n        return [uint256(data.readBytes32(4)), uint256(data.readBytes32(36))];\\n    }\\n}\\n\",\"keccak256\":\"0x406e394eb659ee8c75345b9d3795e0061de2bd6567dd8035e76a19588850f0ea\"}},\"version\":1}",
    -  "bytecode": "0x608060405234801561001057600080fd5b50610f41806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610dd4565b610057565b604051901515815260200160405180910390f35b60006101316002868660405161006e929190610e6e565b602060405180830381855afa15801561008b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906100ae9190610e7e565b6100ed85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061013c92505050565b61012c8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101cb92505050565b61024a565b979650505050505050565b610144610d56565b815160401461019a5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c69642070323536207369676e6174757265206c656e67746800000060448201526064015b60405180910390fd5b60408051808201909152806101b0846000610445565b81526020908101906101c3908590610445565b905292915050565b6101d3610d56565b81516044146102245760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642070323536206b6579206c656e6774680000000000000000006044820152606401610191565b604080518082019091528061023a846004610445565b81526020016101c3846024610445565b8151600090158061027c575082517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255111155b8061028957506020830151155b156102965750600061043e565b815160208301516102a79190610469565b6102b35750600061043e565b6000808080806102ea88600160200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551610565565b905061035a7f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f57fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551848d096105ff565b885160208a01518b5193985091955061039a929091907fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551908590096105ff565b909450915060006103ad868587866106cf565b60408101519091506000036103cb576000965050505050505061043e565b60006103ec8260026020020151600160601b63ffffffff60c01b0319610565565b9050600160601b63ffffffff60c01b0319808283098351098a519091506104337fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255183610ead565b149750505050505050505b9392505050565b8151600090610455836020610ee5565b111561046057600080fd5b50016020015190565b60008215806104855750600160601b63ffffffff60c01b031983145b8061048e575081155b806104a65750600160601b63ffffffff60c01b031982145b156104b35750600061055f565b6000600160601b63ffffffff60c01b031983840990506000600160601b63ffffffff60c01b031985600160601b63ffffffff60c01b0319878809099050600160601b63ffffffff60c01b0319807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc870982089050600160601b63ffffffff60c01b03197f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b820890501490505b92915050565b600082158061057357508183145b8061057c575081155b156105895750600061055f565b818311156105a4578183816105a0576105a0610e97565b0692505b600060018385835b81156105db578183816105c1576105c1610e97565b9495940485810290940393919283830290039190506105ac565b60008512156105f357505050908301915061055f9050565b50929695505050505050565b60008082600003610617576000805b915091506106c7565b826001036106295750839050826106c7565b8260020361063b5761060e85856106f5565b50839050828181600180610650600288610ead565b60000361065f57600094508495505b600187901c96505b86156106b357610678848484610725565b9195509350915061068a600288610ead565b6001036106a75761069f848484898986610983565b919750955090505b600187901c9650610667565b6106be868683610a88565b95509550505050505b935093915050565b6106d7610d74565b6000806106e687878787610ad8565b90925090506101318282610b0d565b600080600061070685856001610725565b91965094509050610718858583610a88565b92509250505b9250929050565b600080600080600080600061073a8a8a610b66565b156107535760006001819650965096505050505061097a565b600160601b63ffffffff60c01b0319888a099250600160601b63ffffffff60c01b0319600284099250600160601b63ffffffff60c01b03198a84099150600160601b63ffffffff60c01b03198983099150600160601b63ffffffff60c01b0319600283099150600160601b63ffffffff60c01b03198a8b099950600160601b63ffffffff60c01b031960038b099350600160601b63ffffffff60c01b03198889099750600160601b63ffffffff60c01b03197fffffffff00000001000000000000000000000000fffffffffffffffffffffffc89099750600160601b63ffffffff60c01b03198885089350600160601b63ffffffff60c01b03198485099050600160601b63ffffffff60c01b0319826002099950600160601b63ffffffff60c01b031961088e8b600160601b63ffffffff60c01b0319610ef8565b82089050600160601b63ffffffff60c01b03196108b982600160601b63ffffffff60c01b0319610ef8565b83089950600160601b63ffffffff60c01b03198a85099950600160601b63ffffffff60c01b0319838a099850600160601b63ffffffff60c01b0319898a099850600160601b63ffffffff60c01b0319896002099850600160601b63ffffffff60c01b03196109358a600160601b63ffffffff60c01b0319610ef8565b8b089550600160601b63ffffffff60c01b03198184099650600160601b63ffffffff60c01b03198384099450600160601b63ffffffff60c01b03198386099450505050505b93509350939050565b60008060008060008060006109988d8d610b66565b156109af5789898996509650965050505050610a7c565b6109b98a8a610b66565b156109d0578c8c8c96509650965050505050610a7c565b600160601b63ffffffff60c01b0319888d099350600160601b63ffffffff60c01b03198b8a099250600160601b63ffffffff60c01b0319888e099150600160601b63ffffffff60c01b03198b8b099050808203610a5257828403610a4857610a398d8d8d610725565b96509650965050505050610a7c565b6000600181610a39565b610a70600160601b63ffffffff60c01b0319898d0983838688610b8a565b91985096509450505050505b96509650969350505050565b6000806000610aa584600160601b63ffffffff60c01b0319610565565b9050600160601b63ffffffff60c01b03198187099250600160601b63ffffffff60c01b0319818609915050935093915050565b6000806000610aed8787600188886001610983565b91985096509050610aff878783610a88565b925092505094509492505050565b610b15610d74565b600160601b63ffffffff60c01b0319600160000860408201819052600160601b63ffffffff60c01b031990840981526040810151600160601b63ffffffff60c01b0319908309602082015292915050565b600082158015610b74575081155b15610b815750600161055f565b50600092915050565b600080808080808080600160601b63ffffffff60c01b0319610bba8b600160601b63ffffffff60c01b0319610ef8565b8a089050600160601b63ffffffff60c01b0319610be58c600160601b63ffffffff60c01b0319610ef8565b8d089450600160601b63ffffffff60c01b03198586099350600160601b63ffffffff60c01b03198182099150600160601b63ffffffff60c01b03198d83099150600160601b63ffffffff60c01b03198c8c089a50600160601b63ffffffff60c01b0319848c099a50600160601b63ffffffff60c01b0319610c748c600160601b63ffffffff60c01b0319610ef8565b83089150600160601b63ffffffff60c01b03198286099750600160601b63ffffffff60c01b03198585099250600160601b63ffffffff60c01b0319848d099b50600160601b63ffffffff60c01b0319610cdb83600160601b63ffffffff60c01b0319610ef8565b8d089b50600160601b63ffffffff60c01b03198c82099050600160601b63ffffffff60c01b0319838a099850600160601b63ffffffff60c01b0319610d2e8a600160601b63ffffffff60c01b0319610ef8565b82089650600160601b63ffffffff60c01b03198d840995505050505050955095509592505050565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60008083601f840112610da457600080fd5b50813567ffffffffffffffff811115610dbc57600080fd5b60208301915083602082850101111561071e57600080fd5b60008060008060008060608789031215610ded57600080fd5b863567ffffffffffffffff80821115610e0557600080fd5b610e118a838b01610d92565b90985096506020890135915080821115610e2a57600080fd5b610e368a838b01610d92565b90965094506040890135915080821115610e4f57600080fd5b50610e5c89828a01610d92565b979a9699509497509295939492505050565b8183823760009101908152919050565b600060208284031215610e9057600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b600082610eca57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b8082018082111561055f5761055f610ecf565b8181038181111561055f5761055f610ecf56fea26469706673582212200a7cdc61343825b33e51ff653c60245b511afc3bf209bfd7831b5eded2744b1c64736f6c63430008110033",
    -  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610dd4565b610057565b604051901515815260200160405180910390f35b60006101316002868660405161006e929190610e6e565b602060405180830381855afa15801561008b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906100ae9190610e7e565b6100ed85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061013c92505050565b61012c8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101cb92505050565b61024a565b979650505050505050565b610144610d56565b815160401461019a5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c69642070323536207369676e6174757265206c656e67746800000060448201526064015b60405180910390fd5b60408051808201909152806101b0846000610445565b81526020908101906101c3908590610445565b905292915050565b6101d3610d56565b81516044146102245760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642070323536206b6579206c656e6774680000000000000000006044820152606401610191565b604080518082019091528061023a846004610445565b81526020016101c3846024610445565b8151600090158061027c575082517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255111155b8061028957506020830151155b156102965750600061043e565b815160208301516102a79190610469565b6102b35750600061043e565b6000808080806102ea88600160200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551610565565b905061035a7f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f57fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551848d096105ff565b885160208a01518b5193985091955061039a929091907fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551908590096105ff565b909450915060006103ad868587866106cf565b60408101519091506000036103cb576000965050505050505061043e565b60006103ec8260026020020151600160601b63ffffffff60c01b0319610565565b9050600160601b63ffffffff60c01b0319808283098351098a519091506104337fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255183610ead565b149750505050505050505b9392505050565b8151600090610455836020610ee5565b111561046057600080fd5b50016020015190565b60008215806104855750600160601b63ffffffff60c01b031983145b8061048e575081155b806104a65750600160601b63ffffffff60c01b031982145b156104b35750600061055f565b6000600160601b63ffffffff60c01b031983840990506000600160601b63ffffffff60c01b031985600160601b63ffffffff60c01b0319878809099050600160601b63ffffffff60c01b0319807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc870982089050600160601b63ffffffff60c01b03197f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b820890501490505b92915050565b600082158061057357508183145b8061057c575081155b156105895750600061055f565b818311156105a4578183816105a0576105a0610e97565b0692505b600060018385835b81156105db578183816105c1576105c1610e97565b9495940485810290940393919283830290039190506105ac565b60008512156105f357505050908301915061055f9050565b50929695505050505050565b60008082600003610617576000805b915091506106c7565b826001036106295750839050826106c7565b8260020361063b5761060e85856106f5565b50839050828181600180610650600288610ead565b60000361065f57600094508495505b600187901c96505b86156106b357610678848484610725565b9195509350915061068a600288610ead565b6001036106a75761069f848484898986610983565b919750955090505b600187901c9650610667565b6106be868683610a88565b95509550505050505b935093915050565b6106d7610d74565b6000806106e687878787610ad8565b90925090506101318282610b0d565b600080600061070685856001610725565b91965094509050610718858583610a88565b92509250505b9250929050565b600080600080600080600061073a8a8a610b66565b156107535760006001819650965096505050505061097a565b600160601b63ffffffff60c01b0319888a099250600160601b63ffffffff60c01b0319600284099250600160601b63ffffffff60c01b03198a84099150600160601b63ffffffff60c01b03198983099150600160601b63ffffffff60c01b0319600283099150600160601b63ffffffff60c01b03198a8b099950600160601b63ffffffff60c01b031960038b099350600160601b63ffffffff60c01b03198889099750600160601b63ffffffff60c01b03197fffffffff00000001000000000000000000000000fffffffffffffffffffffffc89099750600160601b63ffffffff60c01b03198885089350600160601b63ffffffff60c01b03198485099050600160601b63ffffffff60c01b0319826002099950600160601b63ffffffff60c01b031961088e8b600160601b63ffffffff60c01b0319610ef8565b82089050600160601b63ffffffff60c01b03196108b982600160601b63ffffffff60c01b0319610ef8565b83089950600160601b63ffffffff60c01b03198a85099950600160601b63ffffffff60c01b0319838a099850600160601b63ffffffff60c01b0319898a099850600160601b63ffffffff60c01b0319896002099850600160601b63ffffffff60c01b03196109358a600160601b63ffffffff60c01b0319610ef8565b8b089550600160601b63ffffffff60c01b03198184099650600160601b63ffffffff60c01b03198384099450600160601b63ffffffff60c01b03198386099450505050505b93509350939050565b60008060008060008060006109988d8d610b66565b156109af5789898996509650965050505050610a7c565b6109b98a8a610b66565b156109d0578c8c8c96509650965050505050610a7c565b600160601b63ffffffff60c01b0319888d099350600160601b63ffffffff60c01b03198b8a099250600160601b63ffffffff60c01b0319888e099150600160601b63ffffffff60c01b03198b8b099050808203610a5257828403610a4857610a398d8d8d610725565b96509650965050505050610a7c565b6000600181610a39565b610a70600160601b63ffffffff60c01b0319898d0983838688610b8a565b91985096509450505050505b96509650969350505050565b6000806000610aa584600160601b63ffffffff60c01b0319610565565b9050600160601b63ffffffff60c01b03198187099250600160601b63ffffffff60c01b0319818609915050935093915050565b6000806000610aed8787600188886001610983565b91985096509050610aff878783610a88565b925092505094509492505050565b610b15610d74565b600160601b63ffffffff60c01b0319600160000860408201819052600160601b63ffffffff60c01b031990840981526040810151600160601b63ffffffff60c01b0319908309602082015292915050565b600082158015610b74575081155b15610b815750600161055f565b50600092915050565b600080808080808080600160601b63ffffffff60c01b0319610bba8b600160601b63ffffffff60c01b0319610ef8565b8a089050600160601b63ffffffff60c01b0319610be58c600160601b63ffffffff60c01b0319610ef8565b8d089450600160601b63ffffffff60c01b03198586099350600160601b63ffffffff60c01b03198182099150600160601b63ffffffff60c01b03198d83099150600160601b63ffffffff60c01b03198c8c089a50600160601b63ffffffff60c01b0319848c099a50600160601b63ffffffff60c01b0319610c748c600160601b63ffffffff60c01b0319610ef8565b83089150600160601b63ffffffff60c01b03198286099750600160601b63ffffffff60c01b03198585099250600160601b63ffffffff60c01b0319848d099b50600160601b63ffffffff60c01b0319610cdb83600160601b63ffffffff60c01b0319610ef8565b8d089b50600160601b63ffffffff60c01b03198c82099050600160601b63ffffffff60c01b0319838a099850600160601b63ffffffff60c01b0319610d2e8a600160601b63ffffffff60c01b0319610ef8565b82089650600160601b63ffffffff60c01b03198d840995505050505050955095509592505050565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60008083601f840112610da457600080fd5b50813567ffffffffffffffff811115610dbc57600080fd5b60208301915083602082850101111561071e57600080fd5b60008060008060008060608789031215610ded57600080fd5b863567ffffffffffffffff80821115610e0557600080fd5b610e118a838b01610d92565b90985096506020890135915080821115610e2a57600080fd5b610e368a838b01610d92565b90965094506040890135915080821115610e4f57600080fd5b50610e5c89828a01610d92565b979a9699509497509295939492505050565b8183823760009101908152919050565b600060208284031215610e9057600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b600082610eca57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b8082018082111561055f5761055f610ecf565b8181038181111561055f5761055f610ecf56fea26469706673582212200a7cdc61343825b33e51ff653c60245b511afc3bf209bfd7831b5eded2744b1c64736f6c63430008110033",
    +  "contractName": "P256SHA256Algorithm",
    +  "sourceName": "contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol",
    +  "bytecode": "0x6080604052348015600f57600080fd5b5061040f8061001f6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046102db565b610057565b604051901515815260200160405180910390f35b6000604082146100c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c69642070323536207369676e6174757265206c656e67746800000060448201526064015b60405180910390fd5b60448614610132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c69642070323536206b6579206c656e67746800000000000000000060448201526064016100bf565b60405183359060208501359060048a01359060248b0135906101a79060029061015e908c908c90610381565b602060405180830381855afa15801561017b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061019e9190610391565b858585856101b6565b9b9a5050505050505050505050565b604080516020808201889052818301879052606082018690526080820185905260a08083018590528351808403909101815260c083018281526101008401909452600093909284929060e001818036833701905050905060208082018351602085016101005afa925082156102875780517f0100000000000000000000000000000000000000000000000000000000000000908290601f90811061025c5761025c6103aa565b01602001517fff00000000000000000000000000000000000000000000000000000000000000161492505b505095945050505050565b60008083601f8401126102a457600080fd5b50813567ffffffffffffffff8111156102bc57600080fd5b6020830191508360208285010111156102d457600080fd5b9250929050565b600080600080600080606087890312156102f457600080fd5b863567ffffffffffffffff81111561030b57600080fd5b61031789828a01610292565b909750955050602087013567ffffffffffffffff81111561033757600080fd5b61034389828a01610292565b909550935050604087013567ffffffffffffffff81111561036357600080fd5b61036f89828a01610292565b979a9699509497509295939492505050565b8183823760009101908152919050565b6000602082840312156103a357600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea26469706673582212206a9a1972102f1fd2de37e61dcce15b6329edc418622ab7ccd8ac51852a1c48b864736f6c634300081a0033",
    +  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046102db565b610057565b604051901515815260200160405180910390f35b6000604082146100c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c69642070323536207369676e6174757265206c656e67746800000060448201526064015b60405180910390fd5b60448614610132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c69642070323536206b6579206c656e67746800000000000000000060448201526064016100bf565b60405183359060208501359060048a01359060248b0135906101a79060029061015e908c908c90610381565b602060405180830381855afa15801561017b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061019e9190610391565b858585856101b6565b9b9a5050505050505050505050565b604080516020808201889052818301879052606082018690526080820185905260a08083018590528351808403909101815260c083018281526101008401909452600093909284929060e001818036833701905050905060208082018351602085016101005afa925082156102875780517f0100000000000000000000000000000000000000000000000000000000000000908290601f90811061025c5761025c6103aa565b01602001517fff00000000000000000000000000000000000000000000000000000000000000161492505b505095945050505050565b60008083601f8401126102a457600080fd5b50813567ffffffffffffffff8111156102bc57600080fd5b6020830191508360208285010111156102d457600080fd5b9250929050565b600080600080600080606087890312156102f457600080fd5b863567ffffffffffffffff81111561030b57600080fd5b61031789828a01610292565b909750955050602087013567ffffffffffffffff81111561033757600080fd5b61034389828a01610292565b909550935050604087013567ffffffffffffffff81111561036357600080fd5b61036f89828a01610292565b979a9699509497509295939492505050565b8183823760009101908152919050565b6000602082840312156103a357600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea26469706673582212206a9a1972102f1fd2de37e61dcce15b6329edc418622ab7ccd8ac51852a1c48b864736f6c634300081a0033",
    +  "linkReferences": {},
    +  "deployedLinkReferences": {},
    +  "immutableReferences": {},
    +  "inputSourceName": "project/contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol",
       "devdoc": {
    +    "details": "Replaces the Solidity-based EllipticCurve implementation with native P-256 verification",
         "kind": "dev",
         "methods": {
           "verify(bytes,bytes,bytes)": {
    -        "details": "Verifies a signature.",
    +        "details": "Verifies a DNSSEC signature.",
             "params": {
               "data": "The signed data to verify.",
    -          "key": "The public key to verify with.",
    -          "signature": "The signature to verify."
    +          "key": "The DNSKEY RDATA (68 bytes: 4-byte header + 64-byte public key).",
    +          "signature": "The signature to verify (64 bytes: r + s)."
             },
             "returns": {
               "_0": "True iff the signature is valid."
             }
           }
         },
    +    "title": "P256SHA256Algorithm",
         "version": 1
       },
    +  "evm": {
    +    "gasEstimates": {
    +      "creation": {
    +        "codeDepositCost": "207800",
    +        "executionCost": "251",
    +        "totalCost": "208051"
    +      },
    +      "external": {
    +        "verify(bytes,bytes,bytes)": "infinite"
    +      }
    +    }
    +  },
    +  "metadata": "{\"compiler\":{\"version\":\"0.8.26+commit.8a97fa7a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Replaces the Solidity-based EllipticCurve implementation with native P-256 verification\",\"kind\":\"dev\",\"methods\":{\"verify(bytes,bytes,bytes)\":{\"details\":\"Verifies a DNSSEC signature.\",\"params\":{\"data\":\"The signed data to verify.\",\"key\":\"The DNSKEY RDATA (68 bytes: 4-byte header + 64-byte public key).\",\"signature\":\"The signature to verify (64 bytes: r + s).\"},\"returns\":{\"_0\":\"True iff the signature is valid.\"}}},\"title\":\"P256SHA256Algorithm\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"DNSSEC Algorithm 13 (ECDSAP256SHA256) implementation using EIP-7951 precompile\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol\":\"P256SHA256Algorithm\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[\"project/:@ensdomains/solsha1/=npm/@ensdomains/solsha1@0.0.3/\"]},\"sources\":{\"project/contracts/dnssec-oracle/algorithms/Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/// @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\\ninterface Algorithm {\\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    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xbcbdc06d72b64903e733e7ddfbf59c35c984c3eb0022baacab12c97292cc13df\"},\"project/contracts/dnssec-oracle/algorithms/P256Precompile.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary P256Precompile {\\n    /// @dev Verifies a P-256 ECDSA signature using EIP-7951 precompile.\\n    /// @param messageHash The SHA-256 hash of the message being verified.\\n    /// @param r The r component of the signature (32 bytes).\\n    /// @param s The s component of the signature (32 bytes).\\n    /// @param qx The x-coordinate of the public key (32 bytes).\\n    /// @param qy The y-coordinate of the public key (32 bytes).\\n    /// @return success True if the signature is valid, false otherwise.\\n    function verify(\\n        bytes32 messageHash,\\n        bytes32 r,\\n        bytes32 s,\\n        bytes32 qx,\\n        bytes32 qy\\n    ) internal view returns (bool success) {\\n        // EIP-7951 precompile input: hash(32) + r(32) + s(32) + x(32) + y(32) = 160 bytes\\n        bytes memory input = abi.encodePacked(messageHash, r, s, qx, qy);\\n\\n        bytes memory output = new bytes(32);\\n\\n        assembly {\\n            success := staticcall(\\n                gas(),\\n                0x100, // EIP-7951 P-256 precompile address\\n                add(input, 32),\\n                mload(input), // 160 bytes\\n                add(output, 32),\\n                32 // Output is 32 bytes\\n            )\\n        }\\n\\n        // Precompile returns 32 bytes: 0x00...01 for valid, 0x00...00 for invalid\\n        if (success) {\\n            success = (output[31] == bytes1(0x01));\\n        }\\n    }\\n}\\n\\n\",\"keccak256\":\"0x88601b4d6eca961bade47e553477b634a7652827ecb00c488f020c1c86bfccb1\"},\"project/contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"./P256Precompile.sol\\\";\\n\\n/// @title P256SHA256Algorithm\\n/// @notice DNSSEC Algorithm 13 (ECDSAP256SHA256) implementation using EIP-7951 precompile\\n/// @dev Replaces the Solidity-based EllipticCurve implementation with native P-256 verification\\ncontract P256SHA256Algorithm is Algorithm {\\n    /// @dev Verifies a DNSSEC signature.\\n    /// @param key The DNSKEY RDATA (68 bytes: 4-byte header + 64-byte public key).\\n    /// @param data The signed data to verify.\\n    /// @param signature The signature to verify (64 bytes: r + s).\\n    /// @return True iff the signature is valid.\\n    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view override returns (bool) {\\n        require(signature.length == 64, \\\"Invalid p256 signature length\\\");\\n        require(key.length == 68, \\\"Invalid p256 key length\\\");\\n\\n        // Extract signature components (r, s) and public key (qx, qy)\\n        // Key format: 4-byte DNSKEY header (flags, protocol, algorithm) + 64-byte public key\\n        bytes32 r;\\n        bytes32 s;\\n        bytes32 qx;\\n        bytes32 qy;\\n\\n        assembly {\\n            // signature.offset points to start of signature in calldata\\n            r := calldataload(signature.offset)\\n            s := calldataload(add(signature.offset, 32))\\n            // key.offset + 4 skips the DNSKEY header\\n            qx := calldataload(add(key.offset, 4))\\n            qy := calldataload(add(key.offset, 36))\\n        }\\n\\n        return P256Precompile.verify(sha256(data), r, s, qx, qy);\\n    }\\n}\\n\",\"keccak256\":\"0xd204330d635252f9e87d35920d1934c160a45007482916c207fc9dc51549dc81\",\"license\":\"MIT\"}},\"version\":1}",
    +  "storageLayout": {
    +    "storage": [],
    +    "types": null
    +  },
       "userdoc": {
         "kind": "user",
         "methods": {},
    +    "notice": "DNSSEC Algorithm 13 (ECDSAP256SHA256) implementation using EIP-7951 precompile",
         "version": 1
       },
    -  "storageLayout": {
    -    "storage": [],
    -    "types": null
    +  "argsData": "0x",
    +  "transaction": {
    +    "hash": "0xd6644c487b3dcaf557f7aaf0e9b7af4ab372b1534c5de599e2d35b3f12dd54a9",
    +    "nonce": "0x9",
    +    "origin": "0xceed1f4f358e635da87704305c884b4550e82ecb"
    +  },
    +  "receipt": {
    +    "blockHash": "0x531db1aca07b9d5c17870413ccf3801b8e9881d8c7d6e2b2fd6fbed7c9bf97cd",
    +    "blockNumber": "0x9dacb2",
    +    "transactionIndex": "0x5"
       }
     }
    \ No newline at end of file
    
  • deployments/sepolia/RSASHA1Algorithm.json+58 26 modified
    @@ -1,6 +1,22 @@
     {
    -  "address": "0x8FD4107AE8b27B9A83E0BF312Ce414DeEa04Fe94",
    +  "address": "0x81d71df6921f04bbf5347eae737223073ba57646",
       "abi": [
    +    {
    +      "inputs": [
    +        {
    +          "internalType": "uint256",
    +          "name": "offset",
    +          "type": "uint256"
    +        },
    +        {
    +          "internalType": "uint256",
    +          "name": "length",
    +          "type": "uint256"
    +        }
    +      ],
    +      "name": "OffsetOutOfBoundsError",
    +      "type": "error"
    +    },
         {
           "inputs": [
             {
    @@ -31,41 +47,57 @@
           "type": "function"
         }
       ],
    -  "transactionHash": "0xf507480f13718306198224b0859057394b345085a9c2e7e89a3179fb0f99e0ff",
    -  "receipt": {
    -    "to": null,
    -    "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8",
    -    "contractAddress": "0x8FD4107AE8b27B9A83E0BF312Ce414DeEa04Fe94",
    -    "transactionIndex": 91,
    -    "gasUsed": "695194",
    -    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    -    "blockHash": "0x4e10ab00e4a0df8fc18916c429bb6e75159a421899aa90ef69e8eeedc5919588",
    -    "transactionHash": "0xf507480f13718306198224b0859057394b345085a9c2e7e89a3179fb0f99e0ff",
    -    "logs": [],
    -    "blockNumber": 4141613,
    -    "cumulativeGasUsed": "28008584",
    -    "status": 1,
    -    "byzantium": true
    -  },
    -  "args": [],
    -  "numDeployments": 1,
    -  "solcInputHash": "e04502f562d98d0455f6c1c453418cdd",
    -  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements the DNSSEC RSASHA1 algorithm.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol\":\"RSASHA1Algorithm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"@ensdomains/solsha1/contracts/SHA1.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary SHA1 {\\n    event Debug(bytes32 x);\\n\\n    function sha1(bytes memory data) internal pure returns(bytes20 ret) {\\n        assembly {\\n            // Get a safe scratch location\\n            let scratch := mload(0x40)\\n\\n            // Get the data length, and point data at the first byte\\n            let len := mload(data)\\n            data := add(data, 32)\\n\\n            // Find the length after padding\\n            let totallen := add(and(add(len, 1), 0xFFFFFFFFFFFFFFC0), 64)\\n            switch lt(sub(totallen, len), 9)\\n            case 1 { totallen := add(totallen, 64) }\\n\\n            let h := 0x6745230100EFCDAB890098BADCFE001032547600C3D2E1F0\\n\\n            function readword(ptr, off, count) -> result {\\n                result := 0\\n                if lt(off, count) {\\n                    result := mload(add(ptr, off))\\n                    count := sub(count, off)\\n                    if lt(count, 32) {\\n                        let mask := not(sub(exp(256, sub(32, count)), 1))\\n                        result := and(result, mask)\\n                    }\\n                }\\n            }\\n\\n            for { let i := 0 } lt(i, totallen) { i := add(i, 64) } {\\n                mstore(scratch, readword(data, i, len))\\n                mstore(add(scratch, 32), readword(data, add(i, 32), len))\\n\\n                // If we loaded the last byte, store the terminator byte\\n                switch lt(sub(len, i), 64)\\n                case 1 { mstore8(add(scratch, sub(len, i)), 0x80) }\\n\\n                // If this is the last block, store the length\\n                switch eq(i, sub(totallen, 64))\\n                case 1 { mstore(add(scratch, 32), or(mload(add(scratch, 32)), mul(len, 8))) }\\n\\n                // Expand the 16 32-bit words into 80\\n                for { let j := 64 } lt(j, 128) { j := add(j, 12) } {\\n                    let temp := xor(xor(mload(add(scratch, sub(j, 12))), mload(add(scratch, sub(j, 32)))), xor(mload(add(scratch, sub(j, 56))), mload(add(scratch, sub(j, 64)))))\\n                    temp := or(and(mul(temp, 2), 0xFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE), and(div(temp, 0x80000000), 0x0000000100000001000000010000000100000001000000010000000100000001))\\n                    mstore(add(scratch, j), temp)\\n                }\\n                for { let j := 128 } lt(j, 320) { j := add(j, 24) } {\\n                    let temp := xor(xor(mload(add(scratch, sub(j, 24))), mload(add(scratch, sub(j, 64)))), xor(mload(add(scratch, sub(j, 112))), mload(add(scratch, sub(j, 128)))))\\n                    temp := or(and(mul(temp, 4), 0xFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFC), and(div(temp, 0x40000000), 0x0000000300000003000000030000000300000003000000030000000300000003))\\n                    mstore(add(scratch, j), temp)\\n                }\\n\\n                let x := h\\n                let f := 0\\n                let k := 0\\n                for { let j := 0 } lt(j, 80) { j := add(j, 1) } {\\n                    switch div(j, 20)\\n                    case 0 {\\n                        // f = d xor (b and (c xor d))\\n                        f := xor(div(x, 0x100000000000000000000), div(x, 0x10000000000))\\n                        f := and(div(x, 0x1000000000000000000000000000000), f)\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0x5A827999\\n                    }\\n                    case 1{\\n                        // f = b xor c xor d\\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0x6ED9EBA1\\n                    }\\n                    case 2 {\\n                        // f = (b and c) or (d and (b or c))\\n                        f := or(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := and(div(x, 0x10000000000), f)\\n                        f := or(and(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000)), f)\\n                        k := 0x8F1BBCDC\\n                    }\\n                    case 3 {\\n                        // f = b xor c xor d\\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0xCA62C1D6\\n                    }\\n                    // temp = (a leftrotate 5) + f + e + k + w[i]\\n                    let temp := and(div(x, 0x80000000000000000000000000000000000000000000000), 0x1F)\\n                    temp := or(and(div(x, 0x800000000000000000000000000000000000000), 0xFFFFFFE0), temp)\\n                    temp := add(f, temp)\\n                    temp := add(and(x, 0xFFFFFFFF), temp)\\n                    temp := add(k, temp)\\n                    temp := add(div(mload(add(scratch, mul(j, 4))), 0x100000000000000000000000000000000000000000000000000000000), temp)\\n                    x := or(div(x, 0x10000000000), mul(temp, 0x10000000000000000000000000000000000000000))\\n                    x := or(and(x, 0xFFFFFFFF00FFFFFFFF000000000000FFFFFFFF00FFFFFFFF), mul(or(and(div(x, 0x4000000000000), 0xC0000000), and(div(x, 0x400000000000000000000), 0x3FFFFFFF)), 0x100000000000000000000))\\n                }\\n\\n                h := and(add(h, x), 0xFFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF)\\n            }\\n            ret := mul(or(or(or(or(and(div(h, 0x100000000), 0xFFFFFFFF00000000000000000000000000000000), and(div(h, 0x1000000), 0xFFFFFFFF000000000000000000000000)), and(div(h, 0x10000), 0xFFFFFFFF0000000000000000)), and(div(h, 0x100), 0xFFFFFFFF00000000)), and(h, 0xFFFFFFFF)), 0x1000000000000000000000000)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x746d9b85de197afbc13182cbe4ba4f7917f19594e07c655d6a0c85fdf7460a8a\"},\"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/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/algorithms/ModexpPrecompile.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary ModexpPrecompile {\\n    /**\\n     * @dev Computes (base ^ exponent) % modulus over big numbers.\\n     */\\n    function modexp(\\n        bytes memory base,\\n        bytes memory exponent,\\n        bytes memory modulus\\n    ) internal view returns (bool success, bytes memory output) {\\n        bytes memory input = abi.encodePacked(\\n            uint256(base.length),\\n            uint256(exponent.length),\\n            uint256(modulus.length),\\n            base,\\n            exponent,\\n            modulus\\n        );\\n\\n        output = new bytes(modulus.length);\\n\\n        assembly {\\n            success := staticcall(\\n                gas(),\\n                5,\\n                add(input, 32),\\n                mload(input),\\n                add(output, 32),\\n                mload(modulus)\\n            )\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xb3d46284534eb99061d4c79968c2d0420b63a6649d118ef2ea3608396b85de3f\"},\"contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"../BytesUtils.sol\\\";\\nimport \\\"./RSAVerify.sol\\\";\\nimport \\\"@ensdomains/solsha1/contracts/SHA1.sol\\\";\\n\\n/**\\n * @dev Implements the DNSSEC RSASHA1 algorithm.\\n */\\ncontract RSASHA1Algorithm is Algorithm {\\n    using BytesUtils for *;\\n\\n    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata sig\\n    ) external view override returns (bool) {\\n        bytes memory exponent;\\n        bytes memory modulus;\\n\\n        uint16 exponentLen = uint16(key.readUint8(4));\\n        if (exponentLen != 0) {\\n            exponent = key.substring(5, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 5,\\n                key.length - exponentLen - 5\\n            );\\n        } else {\\n            exponentLen = key.readUint16(5);\\n            exponent = key.substring(7, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 7,\\n                key.length - exponentLen - 7\\n            );\\n        }\\n\\n        // Recover the message from the signature\\n        bool ok;\\n        bytes memory result;\\n        (ok, result) = RSAVerify.rsarecover(modulus, exponent, sig);\\n\\n        // Verify it ends with the hash of our data\\n        return ok && SHA1.sha1(data) == result.readBytes20(result.length - 20);\\n    }\\n}\\n\",\"keccak256\":\"0x5dee71f5a212ef48761ab4154fd68fb738eaefe145ee6c3a30d0ed6c63782b55\"},\"contracts/dnssec-oracle/algorithms/RSAVerify.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"../BytesUtils.sol\\\";\\nimport \\\"./ModexpPrecompile.sol\\\";\\n\\nlibrary RSAVerify {\\n    /**\\n     * @dev Recovers the input data from an RSA signature, returning the result in S.\\n     * @param N The RSA public modulus.\\n     * @param E The RSA public exponent.\\n     * @param S The signature to recover.\\n     * @return True if the recovery succeeded.\\n     */\\n    function rsarecover(\\n        bytes memory N,\\n        bytes memory E,\\n        bytes memory S\\n    ) internal view returns (bool, bytes memory) {\\n        return ModexpPrecompile.modexp(S, E, N);\\n    }\\n}\\n\",\"keccak256\":\"0xb386daa80070f79399a2cb97a534f31660161ccd50662fabcf63e26cce064506\"}},\"version\":1}",
    -  "bytecode": "0x608060405234801561001057600080fd5b50610bac806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046109e6565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103009050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b9250610167610107826005610a96565b61ffff9081169060059061011d9085168d610ab8565b6101279190610ab8565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b9150610227565b6101b260058b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103a99050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b925061022461020e826007610a96565b61ffff9081169060079061011d9085168d610ab8565b91505b6000606061026c84868a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103d192505050565b90925090508180156102f057506102916014825161028a9190610ab8565b82906103ec565b6bffffffffffffffffffffffff19166102df8b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061041f92505050565b6bffffffffffffffffffffffff1916145b9c9b505050505050505050505050565b600082828151811061031457610314610acb565b016020015160f81c90505b92915050565b82516060906103348385610ae1565b111561033f57600080fd5b60008267ffffffffffffffff81111561035a5761035a610af4565b6040519080825280601f01601f191660200182016040528015610384576020820181803683370190505b5090506020808201908686010161039c8282876108b0565b50909150505b9392505050565b81516000906103b9836002610ae1565b11156103c457600080fd5b50016002015161ffff1690565b600060606103e0838587610906565b91509150935093915050565b81516000906103fc836014610ae1565b111561040757600080fd5b5001602001516bffffffffffffffffffffffff191690565b60006040518251602084019350604067ffffffffffffffc060018301160160098282031060018103610452576040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f06104a4565b6000838310156103a2575080820151928290039260208410156103a25760001960208590036101000a0119169392505050565b60005b82811015610830576104ba848289610471565b85526104ca846020830189610471565b6020860152604081850310600181036104e65760808286038701535b506040830381146001810361050357602086018051600887021790525b5060405b608081101561058b57858101603f19810151603719820151601f19830151600b198401516002911891909218189081027ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe1663800000009091047c010000000100000001000000010000000100000001000000010000000116179052600c01610507565b5060805b61014081101561061457858101607f19810151606f19820151603f198301516017198401516004911891909218189081027ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc1663400000009091047c03000000030000000300000003000000030000000300000003000000031617905260180161058f565b508160008060005b60508110156108065760148104801561064c576001811461067c57600281146106aa57600381146106dd57610707565b6501000000000085046a010000000000000000000086048118600160781b870416189350635a8279999250610707565b650100000000008504600160781b86046a0100000000000000000000870418189350636ed9eba19250610707565b6a01000000000000000000008504600160781b8604818117650100000000008804169116179350638f1bbcdc9250610707565b650100000000008504600160781b86046a010000000000000000000087041818935063ca62c1d692505b50601f770800000000000000000000000000000000000000000000008504168063ffffffe073080000000000000000000000000000000000000087041617905080840190508063ffffffff86160190508083019050807c0100000000000000000000000000000000000000000000000000000000600484028c015104019050740100000000000000000000000000000000000000008102650100000000008604179450506a0100000000000000000000633fffffff6a040000000000000000000086041663c00000006604000000000000870416170277ffffffff00ffffffff000000000000ffffffff00ffffffff851617935060018101905061061c565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff16906040016104a7565b506c0100000000000000000000000063ffffffff821667ffffffff000000006101008404166bffffffff0000000000000000620100008504166fffffffff000000000000000000000000630100000086041673ffffffff000000000000000000000000000000006401000000008704161717171702945050505050919050565b602081106108e857815183526108c7602084610ae1565b92506108d4602083610ae1565b91506108e1602082610ab8565b90506108b0565b905182516020929092036101000a6000190180199091169116179052565b60006060600085518551855188888860405160200161092a96959493929190610b3a565b6040516020818303038152906040529050835167ffffffffffffffff81111561095557610955610af4565b6040519080825280601f01601f19166020018201604052801561097f576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b60008083601f8401126109af57600080fd5b50813567ffffffffffffffff8111156109c757600080fd5b6020830191508360208285010111156109df57600080fd5b9250929050565b600080600080600080606087890312156109ff57600080fd5b863567ffffffffffffffff80821115610a1757600080fd5b610a238a838b0161099d565b90985096506020890135915080821115610a3c57600080fd5b610a488a838b0161099d565b90965094506040890135915080821115610a6157600080fd5b50610a6e89828a0161099d565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b61ffff818116838216019080821115610ab157610ab1610a80565b5092915050565b8181038181111561031f5761031f610a80565b634e487b7160e01b600052603260045260246000fd5b8082018082111561031f5761031f610a80565b634e487b7160e01b600052604160045260246000fd5b6000815160005b81811015610b2b5760208185018101518683015201610b11565b50600093019283525090919050565b8681528560208201528460408201526000610b6a610b64610b5e6060850188610b0a565b86610b0a565b84610b0a565b9897505050505050505056fea26469706673582212207857b7c8a67e5fd64e3ccb8e7b2e6fbd8ac879a5659d7498b1bc12aeeba36c9764736f6c63430008110033",
    -  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046109e6565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103009050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b9250610167610107826005610a96565b61ffff9081169060059061011d9085168d610ab8565b6101279190610ab8565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b9150610227565b6101b260058b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103a99050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103259050565b925061022461020e826007610a96565b61ffff9081169060079061011d9085168d610ab8565b91505b6000606061026c84868a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103d192505050565b90925090508180156102f057506102916014825161028a9190610ab8565b82906103ec565b6bffffffffffffffffffffffff19166102df8b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061041f92505050565b6bffffffffffffffffffffffff1916145b9c9b505050505050505050505050565b600082828151811061031457610314610acb565b016020015160f81c90505b92915050565b82516060906103348385610ae1565b111561033f57600080fd5b60008267ffffffffffffffff81111561035a5761035a610af4565b6040519080825280601f01601f191660200182016040528015610384576020820181803683370190505b5090506020808201908686010161039c8282876108b0565b50909150505b9392505050565b81516000906103b9836002610ae1565b11156103c457600080fd5b50016002015161ffff1690565b600060606103e0838587610906565b91509150935093915050565b81516000906103fc836014610ae1565b111561040757600080fd5b5001602001516bffffffffffffffffffffffff191690565b60006040518251602084019350604067ffffffffffffffc060018301160160098282031060018103610452576040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f06104a4565b6000838310156103a2575080820151928290039260208410156103a25760001960208590036101000a0119169392505050565b60005b82811015610830576104ba848289610471565b85526104ca846020830189610471565b6020860152604081850310600181036104e65760808286038701535b506040830381146001810361050357602086018051600887021790525b5060405b608081101561058b57858101603f19810151603719820151601f19830151600b198401516002911891909218189081027ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe1663800000009091047c010000000100000001000000010000000100000001000000010000000116179052600c01610507565b5060805b61014081101561061457858101607f19810151606f19820151603f198301516017198401516004911891909218189081027ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc1663400000009091047c03000000030000000300000003000000030000000300000003000000031617905260180161058f565b508160008060005b60508110156108065760148104801561064c576001811461067c57600281146106aa57600381146106dd57610707565b6501000000000085046a010000000000000000000086048118600160781b870416189350635a8279999250610707565b650100000000008504600160781b86046a0100000000000000000000870418189350636ed9eba19250610707565b6a01000000000000000000008504600160781b8604818117650100000000008804169116179350638f1bbcdc9250610707565b650100000000008504600160781b86046a010000000000000000000087041818935063ca62c1d692505b50601f770800000000000000000000000000000000000000000000008504168063ffffffe073080000000000000000000000000000000000000087041617905080840190508063ffffffff86160190508083019050807c0100000000000000000000000000000000000000000000000000000000600484028c015104019050740100000000000000000000000000000000000000008102650100000000008604179450506a0100000000000000000000633fffffff6a040000000000000000000086041663c00000006604000000000000870416170277ffffffff00ffffffff000000000000ffffffff00ffffffff851617935060018101905061061c565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff16906040016104a7565b506c0100000000000000000000000063ffffffff821667ffffffff000000006101008404166bffffffff0000000000000000620100008504166fffffffff000000000000000000000000630100000086041673ffffffff000000000000000000000000000000006401000000008704161717171702945050505050919050565b602081106108e857815183526108c7602084610ae1565b92506108d4602083610ae1565b91506108e1602082610ab8565b90506108b0565b905182516020929092036101000a6000190180199091169116179052565b60006060600085518551855188888860405160200161092a96959493929190610b3a565b6040516020818303038152906040529050835167ffffffffffffffff81111561095557610955610af4565b6040519080825280601f01601f19166020018201604052801561097f576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b60008083601f8401126109af57600080fd5b50813567ffffffffffffffff8111156109c757600080fd5b6020830191508360208285010111156109df57600080fd5b9250929050565b600080600080600080606087890312156109ff57600080fd5b863567ffffffffffffffff80821115610a1757600080fd5b610a238a838b0161099d565b90985096506020890135915080821115610a3c57600080fd5b610a488a838b0161099d565b90965094506040890135915080821115610a6157600080fd5b50610a6e89828a0161099d565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b61ffff818116838216019080821115610ab157610ab1610a80565b5092915050565b8181038181111561031f5761031f610a80565b634e487b7160e01b600052603260045260246000fd5b8082018082111561031f5761031f610a80565b634e487b7160e01b600052604160045260246000fd5b6000815160005b81811015610b2b5760208185018101518683015201610b11565b50600093019283525090919050565b8681528560208201528460408201526000610b6a610b64610b5e6060850188610b0a565b86610b0a565b84610b0a565b9897505050505050505056fea26469706673582212207857b7c8a67e5fd64e3ccb8e7b2e6fbd8ac879a5659d7498b1bc12aeeba36c9764736f6c63430008110033",
    +  "contractName": "RSASHA1Algorithm",
    +  "sourceName": "contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol",
    +  "bytecode": "0x6080604052348015600f57600080fd5b506110c48061001f6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610eaf565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102c39050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b9250610167610107826005610f84565b61ffff9081169060059061011d9085168d610f9e565b6101279190610f9e565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b9150610227565b6101b260058b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103599050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b925061022461020e826007610f84565b61ffff9081169060079061011d9085168d610f9e565b91505b6102b5828488888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506102b08c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061037692505050565b610945565b9a9950505050505050505050565b60006102d9836102d4846001610fb1565b6109e2565b8282815181106102eb576102eb610fc4565b016020015160f81c90505b92915050565b60608167ffffffffffffffff81111561031757610317610ff3565b6040519080825280601f01601f191660200182016040528015610341576020820181803683370190505b509050610352848483600086610a37565b9392505050565b600061036a836102d4846002610fb1565b50016020015160f01c90565b60006040518251602084019350604067ffffffffffffffc0600183011601600982820310600181036103a9576040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f0610419565b60008383101561035257508082015192829003926020841015610352577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208590036101000a0119169392505050565b60005b828110156108c55761042f8482896103c8565b855261043f8460208301896103c8565b60208601526040818503106001810361045b5760808286038701535b506040830381146001810361047857602086018051600887021790525b5060405b6080811015610578578581017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc88201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff48401516002911891909218189081027ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe1663800000009091047c010000000100000001000000010000000100000001000000010000000116179052600c0161047c565b5060805b610140811015610679578581017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08301517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe88401516004911891909218189081027ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc1663400000009091047c03000000030000000300000003000000030000000300000003000000031617905260180161057c565b508160008060005b605081101561089b576014810480156106b157600181146106ed576002811461072757600381146107665761079c565b6501000000000085046a0100000000000000000000860481186f01000000000000000000000000000000870416189350635a827999925061079c565b6501000000000085046f0100000000000000000000000000000086046a0100000000000000000000870418189350636ed9eba1925061079c565b6a010000000000000000000085046f010000000000000000000000000000008604818117650100000000008804169116179350638f1bbcdc925061079c565b6501000000000085046f0100000000000000000000000000000086046a010000000000000000000087041818935063ca62c1d692505b50601f770800000000000000000000000000000000000000000000008504168063ffffffe073080000000000000000000000000000000000000087041617905080840190508063ffffffff86160190508083019050807c0100000000000000000000000000000000000000000000000000000000600484028c015104019050740100000000000000000000000000000000000000008102650100000000008604179450506a0100000000000000000000633fffffff6a040000000000000000000086041663c00000006604000000000000870416170277ffffffff00ffffffff000000000000ffffffff00ffffffff8516179350600181019050610681565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff169060400161041c565b506c0100000000000000000000000063ffffffff821667ffffffff000000006101008404166bffffffff0000000000000000620100008504166fffffffff000000000000000000000000630100000086041673ffffffff000000000000000000000000000000006401000000008704161717171702945050505050919050565b600080600061098b8787876040518060400160405280600f81526020017f3021300906052b0e03021a050004140000000000000000000000000000000000815250610a6f565b915091508180156109d757506109af601482516109a89190610f9e565b8290610cd4565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008581169116145b979650505050505050565b8151811115610a335781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610a2a918391600401918252602082015260400190565b60405180910390fd5b5050565b610a45856102d48387610fb1565b610a53836102d48385610fb1565b610a6882602085010185602088010183610cf1565b5050505050565b60006060600080610a81888888610d77565b91509150811580610a9457508751815114155b15610aa657600093509150610ccb9050565b80600081518110610ab957610ab9610fc4565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016151580610b47575080600181518110610afb57610afb610fc4565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f010000000000000000000000000000000000000000000000000000000000000014155b15610b5957600093509150610ccb9050565b60008551600f14610b6b576020610b6e565b60145b60ff1690506000818351610b829190610f9e565b90506000875182610b939190610f9e565b905083610ba1600183610f9e565b81518110610bb157610bb1610fc4565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615610bee57600084965096505050505050610ccb565b8751610c0290859083908b90600090610d92565b610c1757600084965096505050505050610ccb565b60006002610c26600184610f9e565b610c309190610f9e565b90506008811015610c4d5760008597509750505050505050610ccb565b60025b610c5b600184610f9e565b811015610cbd57858181518110610c7457610c74610fc4565b01602001517fff0000000000000000000000000000000000000000000000000000000000000090811614610cb5576000869850985050505050505050610ccb565b600101610c50565b506001975093955050505050505b94509492505050565b6000610ce5836102d4846014610fb1565b50016014015160601b90565b5b601f811115610d305781518352602092830192909101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001610cf2565b8015610d7257815183516001602084900360031b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161783525b505050565b60006060610d86838587610db5565b91509150935093915050565b6000610d9f848484610e4c565b610daa878785610e4c565b149695505050505050565b600060606000855185518551888888604051602001610dd996959493929190611052565b6040516020818303038152906040529050835167ffffffffffffffff811115610e0457610e04610ff3565b6040519080825280601f01601f191660200182016040528015610e2e576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b6000610e5c846102d48486610fb1565b5091016020012090565b60008083601f840112610e7857600080fd5b50813567ffffffffffffffff811115610e9057600080fd5b602083019150836020828501011115610ea857600080fd5b9250929050565b60008060008060008060608789031215610ec857600080fd5b863567ffffffffffffffff811115610edf57600080fd5b610eeb89828a01610e66565b909750955050602087013567ffffffffffffffff811115610f0b57600080fd5b610f1789828a01610e66565b909550935050604087013567ffffffffffffffff811115610f3757600080fd5b610f4389828a01610e66565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff81811683821601908111156102f6576102f6610f55565b818103818111156102f6576102f6610f55565b808201808211156102f6576102f6610f55565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000815160005b818110156110435760208185018101518683015201611029565b50600093019283525090919050565b868152856020820152846040820152600061108261107c6110766060850188611022565b86611022565b84611022565b9897505050505050505056fea264697066735822122016a90630cdc11b5bbd0fa46e4576311b3615cc9991b0025f3ed883bf3156890b64736f6c634300081a0033",
    +  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610eaf565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102c39050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b9250610167610107826005610f84565b61ffff9081169060059061011d9085168d610f9e565b6101279190610f9e565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b9150610227565b6101b260058b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506103599050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102fc9050565b925061022461020e826007610f84565b61ffff9081169060079061011d9085168d610f9e565b91505b6102b5828488888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506102b08c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061037692505050565b610945565b9a9950505050505050505050565b60006102d9836102d4846001610fb1565b6109e2565b8282815181106102eb576102eb610fc4565b016020015160f81c90505b92915050565b60608167ffffffffffffffff81111561031757610317610ff3565b6040519080825280601f01601f191660200182016040528015610341576020820181803683370190505b509050610352848483600086610a37565b9392505050565b600061036a836102d4846002610fb1565b50016020015160f01c90565b60006040518251602084019350604067ffffffffffffffc0600183011601600982820310600181036103a9576040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f0610419565b60008383101561035257508082015192829003926020841015610352577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208590036101000a0119169392505050565b60005b828110156108c55761042f8482896103c8565b855261043f8460208301896103c8565b60208601526040818503106001810361045b5760808286038701535b506040830381146001810361047857602086018051600887021790525b5060405b6080811015610578578581017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc88201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff48401516002911891909218189081027ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe1663800000009091047c010000000100000001000000010000000100000001000000010000000116179052600c0161047c565b5060805b610140811015610679578581017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08301517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe88401516004911891909218189081027ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc1663400000009091047c03000000030000000300000003000000030000000300000003000000031617905260180161057c565b508160008060005b605081101561089b576014810480156106b157600181146106ed576002811461072757600381146107665761079c565b6501000000000085046a0100000000000000000000860481186f01000000000000000000000000000000870416189350635a827999925061079c565b6501000000000085046f0100000000000000000000000000000086046a0100000000000000000000870418189350636ed9eba1925061079c565b6a010000000000000000000085046f010000000000000000000000000000008604818117650100000000008804169116179350638f1bbcdc925061079c565b6501000000000085046f0100000000000000000000000000000086046a010000000000000000000087041818935063ca62c1d692505b50601f770800000000000000000000000000000000000000000000008504168063ffffffe073080000000000000000000000000000000000000087041617905080840190508063ffffffff86160190508083019050807c0100000000000000000000000000000000000000000000000000000000600484028c015104019050740100000000000000000000000000000000000000008102650100000000008604179450506a0100000000000000000000633fffffff6a040000000000000000000086041663c00000006604000000000000870416170277ffffffff00ffffffff000000000000ffffffff00ffffffff8516179350600181019050610681565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff169060400161041c565b506c0100000000000000000000000063ffffffff821667ffffffff000000006101008404166bffffffff0000000000000000620100008504166fffffffff000000000000000000000000630100000086041673ffffffff000000000000000000000000000000006401000000008704161717171702945050505050919050565b600080600061098b8787876040518060400160405280600f81526020017f3021300906052b0e03021a050004140000000000000000000000000000000000815250610a6f565b915091508180156109d757506109af601482516109a89190610f9e565b8290610cd4565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008581169116145b979650505050505050565b8151811115610a335781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610a2a918391600401918252602082015260400190565b60405180910390fd5b5050565b610a45856102d48387610fb1565b610a53836102d48385610fb1565b610a6882602085010185602088010183610cf1565b5050505050565b60006060600080610a81888888610d77565b91509150811580610a9457508751815114155b15610aa657600093509150610ccb9050565b80600081518110610ab957610ab9610fc4565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016151580610b47575080600181518110610afb57610afb610fc4565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f010000000000000000000000000000000000000000000000000000000000000014155b15610b5957600093509150610ccb9050565b60008551600f14610b6b576020610b6e565b60145b60ff1690506000818351610b829190610f9e565b90506000875182610b939190610f9e565b905083610ba1600183610f9e565b81518110610bb157610bb1610fc4565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615610bee57600084965096505050505050610ccb565b8751610c0290859083908b90600090610d92565b610c1757600084965096505050505050610ccb565b60006002610c26600184610f9e565b610c309190610f9e565b90506008811015610c4d5760008597509750505050505050610ccb565b60025b610c5b600184610f9e565b811015610cbd57858181518110610c7457610c74610fc4565b01602001517fff0000000000000000000000000000000000000000000000000000000000000090811614610cb5576000869850985050505050505050610ccb565b600101610c50565b506001975093955050505050505b94509492505050565b6000610ce5836102d4846014610fb1565b50016014015160601b90565b5b601f811115610d305781518352602092830192909101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001610cf2565b8015610d7257815183516001602084900360031b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161783525b505050565b60006060610d86838587610db5565b91509150935093915050565b6000610d9f848484610e4c565b610daa878785610e4c565b149695505050505050565b600060606000855185518551888888604051602001610dd996959493929190611052565b6040516020818303038152906040529050835167ffffffffffffffff811115610e0457610e04610ff3565b6040519080825280601f01601f191660200182016040528015610e2e576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b6000610e5c846102d48486610fb1565b5091016020012090565b60008083601f840112610e7857600080fd5b50813567ffffffffffffffff811115610e9057600080fd5b602083019150836020828501011115610ea857600080fd5b9250929050565b60008060008060008060608789031215610ec857600080fd5b863567ffffffffffffffff811115610edf57600080fd5b610eeb89828a01610e66565b909750955050602087013567ffffffffffffffff811115610f0b57600080fd5b610f1789828a01610e66565b909550935050604087013567ffffffffffffffff811115610f3757600080fd5b610f4389828a01610e66565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff81811683821601908111156102f6576102f6610f55565b818103818111156102f6576102f6610f55565b808201808211156102f6576102f6610f55565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000815160005b818110156110435760208185018101518683015201611029565b50600093019283525090919050565b868152856020820152846040820152600061108261107c6110766060850188611022565b86611022565b84611022565b9897505050505050505056fea264697066735822122016a90630cdc11b5bbd0fa46e4576311b3615cc9991b0025f3ed883bf3156890b64736f6c634300081a0033",
    +  "linkReferences": {},
    +  "deployedLinkReferences": {},
    +  "immutableReferences": {},
    +  "inputSourceName": "project/contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol",
       "devdoc": {
         "details": "Implements the DNSSEC RSASHA1 algorithm.",
    +    "errors": {
    +      "OffsetOutOfBoundsError(uint256,uint256)": [
    +        {
    +          "details": "`offset` was beyond `length`.       Error selector: `0x8a3c1cfb`"
    +        }
    +      ]
    +    },
         "kind": "dev",
         "methods": {},
         "version": 1
       },
    +  "evm": {
    +    "gasEstimates": {
    +      "creation": {
    +        "codeDepositCost": "858400",
    +        "executionCost": "896",
    +        "totalCost": "859296"
    +      },
    +      "external": {
    +        "verify(bytes,bytes,bytes)": "infinite"
    +      }
    +    }
    +  },
    +  "metadata": "{\"compiler\":{\"version\":\"0.8.26+commit.8a97fa7a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements the DNSSEC RSASHA1 algorithm.\",\"errors\":{\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`.       Error selector: `0x8a3c1cfb`\"}]},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol\":\"RSASHA1Algorithm\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[\"project/:@ensdomains/solsha1/=npm/@ensdomains/solsha1@0.0.3/\"]},\"sources\":{\"npm/@ensdomains/solsha1@0.0.3/contracts/SHA1.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary SHA1 {\\n    event Debug(bytes32 x);\\n\\n    function sha1(bytes memory data) internal pure returns(bytes20 ret) {\\n        assembly {\\n            // Get a safe scratch location\\n            let scratch := mload(0x40)\\n\\n            // Get the data length, and point data at the first byte\\n            let len := mload(data)\\n            data := add(data, 32)\\n\\n            // Find the length after padding\\n            let totallen := add(and(add(len, 1), 0xFFFFFFFFFFFFFFC0), 64)\\n            switch lt(sub(totallen, len), 9)\\n            case 1 { totallen := add(totallen, 64) }\\n\\n            let h := 0x6745230100EFCDAB890098BADCFE001032547600C3D2E1F0\\n\\n            function readword(ptr, off, count) -> result {\\n                result := 0\\n                if lt(off, count) {\\n                    result := mload(add(ptr, off))\\n                    count := sub(count, off)\\n                    if lt(count, 32) {\\n                        let mask := not(sub(exp(256, sub(32, count)), 1))\\n                        result := and(result, mask)\\n                    }\\n                }\\n            }\\n\\n            for { let i := 0 } lt(i, totallen) { i := add(i, 64) } {\\n                mstore(scratch, readword(data, i, len))\\n                mstore(add(scratch, 32), readword(data, add(i, 32), len))\\n\\n                // If we loaded the last byte, store the terminator byte\\n                switch lt(sub(len, i), 64)\\n                case 1 { mstore8(add(scratch, sub(len, i)), 0x80) }\\n\\n                // If this is the last block, store the length\\n                switch eq(i, sub(totallen, 64))\\n                case 1 { mstore(add(scratch, 32), or(mload(add(scratch, 32)), mul(len, 8))) }\\n\\n                // Expand the 16 32-bit words into 80\\n                for { let j := 64 } lt(j, 128) { j := add(j, 12) } {\\n                    let temp := xor(xor(mload(add(scratch, sub(j, 12))), mload(add(scratch, sub(j, 32)))), xor(mload(add(scratch, sub(j, 56))), mload(add(scratch, sub(j, 64)))))\\n                    temp := or(and(mul(temp, 2), 0xFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE), and(div(temp, 0x80000000), 0x0000000100000001000000010000000100000001000000010000000100000001))\\n                    mstore(add(scratch, j), temp)\\n                }\\n                for { let j := 128 } lt(j, 320) { j := add(j, 24) } {\\n                    let temp := xor(xor(mload(add(scratch, sub(j, 24))), mload(add(scratch, sub(j, 64)))), xor(mload(add(scratch, sub(j, 112))), mload(add(scratch, sub(j, 128)))))\\n                    temp := or(and(mul(temp, 4), 0xFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFC), and(div(temp, 0x40000000), 0x0000000300000003000000030000000300000003000000030000000300000003))\\n                    mstore(add(scratch, j), temp)\\n                }\\n\\n                let x := h\\n                let f := 0\\n                let k := 0\\n                for { let j := 0 } lt(j, 80) { j := add(j, 1) } {\\n                    switch div(j, 20)\\n                    case 0 {\\n                        // f = d xor (b and (c xor d))\\n                        f := xor(div(x, 0x100000000000000000000), div(x, 0x10000000000))\\n                        f := and(div(x, 0x1000000000000000000000000000000), f)\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0x5A827999\\n                    }\\n                    case 1{\\n                        // f = b xor c xor d\\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0x6ED9EBA1\\n                    }\\n                    case 2 {\\n                        // f = (b and c) or (d and (b or c))\\n                        f := or(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := and(div(x, 0x10000000000), f)\\n                        f := or(and(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000)), f)\\n                        k := 0x8F1BBCDC\\n                    }\\n                    case 3 {\\n                        // f = b xor c xor d\\n                        f := xor(div(x, 0x1000000000000000000000000000000), div(x, 0x100000000000000000000))\\n                        f := xor(div(x, 0x10000000000), f)\\n                        k := 0xCA62C1D6\\n                    }\\n                    // temp = (a leftrotate 5) + f + e + k + w[i]\\n                    let temp := and(div(x, 0x80000000000000000000000000000000000000000000000), 0x1F)\\n                    temp := or(and(div(x, 0x800000000000000000000000000000000000000), 0xFFFFFFE0), temp)\\n                    temp := add(f, temp)\\n                    temp := add(and(x, 0xFFFFFFFF), temp)\\n                    temp := add(k, temp)\\n                    temp := add(div(mload(add(scratch, mul(j, 4))), 0x100000000000000000000000000000000000000000000000000000000), temp)\\n                    x := or(div(x, 0x10000000000), mul(temp, 0x10000000000000000000000000000000000000000))\\n                    x := or(and(x, 0xFFFFFFFF00FFFFFFFF000000000000FFFFFFFF00FFFFFFFF), mul(or(and(div(x, 0x4000000000000), 0xC0000000), and(div(x, 0x400000000000000000000), 0x3FFFFFFF)), 0x100000000000000000000))\\n                }\\n\\n                h := and(add(h, x), 0xFFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF)\\n            }\\n            ret := mul(or(or(or(or(and(div(h, 0x100000000), 0xFFFFFFFF00000000000000000000000000000000), and(div(h, 0x1000000), 0xFFFFFFFF000000000000000000000000)), and(div(h, 0x10000), 0xFFFFFFFF0000000000000000)), and(div(h, 0x100), 0xFFFFFFFF00000000)), and(h, 0xFFFFFFFF)), 0x1000000000000000000000000)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x746d9b85de197afbc13182cbe4ba4f7917f19594e07c655d6a0c85fdf7460a8a\"},\"project/contracts/dnssec-oracle/algorithms/Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/// @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\\ninterface Algorithm {\\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    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xbcbdc06d72b64903e733e7ddfbf59c35c984c3eb0022baacab12c97292cc13df\"},\"project/contracts/dnssec-oracle/algorithms/ModexpPrecompile.sol\":{\"content\":\"pragma solidity ^0.8.4
    ... [truncated]
    
  • deployments/sepolia/RSASHA256Algorithm.json+59 26 modified
    @@ -1,6 +1,22 @@
     {
    -  "address": "0xd63a22BB8076022373E0577E10e3585A53B3b9Ce",
    +  "address": "0xa1fdd748479064bc4386ff8af7ea14da8760172b",
       "abi": [
    +    {
    +      "inputs": [
    +        {
    +          "internalType": "uint256",
    +          "name": "offset",
    +          "type": "uint256"
    +        },
    +        {
    +          "internalType": "uint256",
    +          "name": "length",
    +          "type": "uint256"
    +        }
    +      ],
    +      "name": "OffsetOutOfBoundsError",
    +      "type": "error"
    +    },
         {
           "inputs": [
             {
    @@ -31,41 +47,58 @@
           "type": "function"
         }
       ],
    -  "transactionHash": "0x3cb1273130bb057b878a138a2b3e6368b27ad4f1b703bf1fa9330fc8c2f0f010",
    -  "receipt": {
    -    "to": null,
    -    "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8",
    -    "contractAddress": "0xd63a22BB8076022373E0577E10e3585A53B3b9Ce",
    -    "transactionIndex": 157,
    -    "gasUsed": "448967",
    -    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    -    "blockHash": "0x6e84cefadfc39dff680deeb73b9d73a961cdaa4cdbfd5327f1ed0baf6f845360",
    -    "transactionHash": "0x3cb1273130bb057b878a138a2b3e6368b27ad4f1b703bf1fa9330fc8c2f0f010",
    -    "logs": [],
    -    "blockNumber": 4141616,
    -    "cumulativeGasUsed": "19003956",
    -    "status": 1,
    -    "byzantium": true
    -  },
    -  "args": [],
    -  "numDeployments": 1,
    -  "solcInputHash": "e04502f562d98d0455f6c1c453418cdd",
    -  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements the DNSSEC RSASHA256 algorithm.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol\":\"RSASHA256Algorithm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"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/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/algorithms/ModexpPrecompile.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary ModexpPrecompile {\\n    /**\\n     * @dev Computes (base ^ exponent) % modulus over big numbers.\\n     */\\n    function modexp(\\n        bytes memory base,\\n        bytes memory exponent,\\n        bytes memory modulus\\n    ) internal view returns (bool success, bytes memory output) {\\n        bytes memory input = abi.encodePacked(\\n            uint256(base.length),\\n            uint256(exponent.length),\\n            uint256(modulus.length),\\n            base,\\n            exponent,\\n            modulus\\n        );\\n\\n        output = new bytes(modulus.length);\\n\\n        assembly {\\n            success := staticcall(\\n                gas(),\\n                5,\\n                add(input, 32),\\n                mload(input),\\n                add(output, 32),\\n                mload(modulus)\\n            )\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xb3d46284534eb99061d4c79968c2d0420b63a6649d118ef2ea3608396b85de3f\"},\"contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"../BytesUtils.sol\\\";\\nimport \\\"./RSAVerify.sol\\\";\\n\\n/**\\n * @dev Implements the DNSSEC RSASHA256 algorithm.\\n */\\ncontract RSASHA256Algorithm is Algorithm {\\n    using BytesUtils for *;\\n\\n    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata sig\\n    ) external view override returns (bool) {\\n        bytes memory exponent;\\n        bytes memory modulus;\\n\\n        uint16 exponentLen = uint16(key.readUint8(4));\\n        if (exponentLen != 0) {\\n            exponent = key.substring(5, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 5,\\n                key.length - exponentLen - 5\\n            );\\n        } else {\\n            exponentLen = key.readUint16(5);\\n            exponent = key.substring(7, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 7,\\n                key.length - exponentLen - 7\\n            );\\n        }\\n\\n        // Recover the message from the signature\\n        bool ok;\\n        bytes memory result;\\n        (ok, result) = RSAVerify.rsarecover(modulus, exponent, sig);\\n\\n        // Verify it ends with the hash of our data\\n        return ok && sha256(data) == result.readBytes32(result.length - 32);\\n    }\\n}\\n\",\"keccak256\":\"0x1d6ba44f41e957f9c53e6e5b88150cbb6c9f46e9da196502984ee0a53e9ac5a9\"},\"contracts/dnssec-oracle/algorithms/RSAVerify.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"../BytesUtils.sol\\\";\\nimport \\\"./ModexpPrecompile.sol\\\";\\n\\nlibrary RSAVerify {\\n    /**\\n     * @dev Recovers the input data from an RSA signature, returning the result in S.\\n     * @param N The RSA public modulus.\\n     * @param E The RSA public exponent.\\n     * @param S The signature to recover.\\n     * @return True if the recovery succeeded.\\n     */\\n    function rsarecover(\\n        bytes memory N,\\n        bytes memory E,\\n        bytes memory S\\n    ) internal view returns (bool, bytes memory) {\\n        return ModexpPrecompile.modexp(S, E, N);\\n    }\\n}\\n\",\"keccak256\":\"0xb386daa80070f79399a2cb97a534f31660161ccd50662fabcf63e26cce064506\"}},\"version\":1}",
    -  "bytecode": "0x608060405234801561001057600080fd5b50610728806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610539565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102f59050565b60ff169050801561016e576100f760058261ffff168c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b92506101676101078260056105e9565b61ffff9081169060059061011d9085168d61060b565b610127919061060b565b8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b9150610227565b6101b260058b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061039c9050565b90506101fe60078261ffff168c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b925061022461020e8260076105e9565b61ffff9081169060079061011d9085168d61060b565b91505b6000606061026c84868a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103c492505050565b90925090508180156102e557506102916020825161028a919061060b565b82906103df565b60028b8b6040516102a392919061061e565b602060405180830381855afa1580156102c0573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906102e3919061062e565b145b9c9b505050505050505050505050565b600082828151811061030957610309610647565b016020015160f81c90505b92915050565b8251606090610329838561065d565b111561033457600080fd5b60008267ffffffffffffffff81111561034f5761034f610670565b6040519080825280601f01601f191660200182016040528015610379576020820181803683370190505b50905060208082019086860101610391828287610403565b509095945050505050565b81516000906103ac83600261065d565b11156103b757600080fd5b50016002015161ffff1690565b600060606103d3838587610459565b91509150935093915050565b81516000906103ef83602061065d565b11156103fa57600080fd5b50016020015190565b6020811061043b578151835261041a60208461065d565b925061042760208361065d565b915061043460208261060b565b9050610403565b905182516020929092036101000a6000190180199091169116179052565b60006060600085518551855188888860405160200161047d969594939291906106b6565b6040516020818303038152906040529050835167ffffffffffffffff8111156104a8576104a8610670565b6040519080825280601f01601f1916602001820160405280156104d2576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b60008083601f84011261050257600080fd5b50813567ffffffffffffffff81111561051a57600080fd5b60208301915083602082850101111561053257600080fd5b9250929050565b6000806000806000806060878903121561055257600080fd5b863567ffffffffffffffff8082111561056a57600080fd5b6105768a838b016104f0565b9098509650602089013591508082111561058f57600080fd5b61059b8a838b016104f0565b909650945060408901359150808211156105b457600080fd5b506105c189828a016104f0565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b61ffff818116838216019080821115610604576106046105d3565b5092915050565b81810381811115610314576103146105d3565b8183823760009101908152919050565b60006020828403121561064057600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b80820180821115610314576103146105d3565b634e487b7160e01b600052604160045260246000fd5b6000815160005b818110156106a7576020818501810151868301520161068d565b50600093019283525090919050565b86815285602082015284604082015260006106e66106e06106da6060850188610686565b86610686565b84610686565b9897505050505050505056fea264697066735822122081d54f6872821586c976d8d9aa106e2ea811afa445a713b0da099f753dd8e48364736f6c63430008110033",
    -  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610539565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102f59050565b60ff169050801561016e576100f760058261ffff168c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b92506101676101078260056105e9565b61ffff9081169060059061011d9085168d61060b565b610127919061060b565b8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b9150610227565b6101b260058b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061039c9050565b90506101fe60078261ffff168c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505061031a9050565b925061022461020e8260076105e9565b61ffff9081169060079061011d9085168d61060b565b91505b6000606061026c84868a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103c492505050565b90925090508180156102e557506102916020825161028a919061060b565b82906103df565b60028b8b6040516102a392919061061e565b602060405180830381855afa1580156102c0573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906102e3919061062e565b145b9c9b505050505050505050505050565b600082828151811061030957610309610647565b016020015160f81c90505b92915050565b8251606090610329838561065d565b111561033457600080fd5b60008267ffffffffffffffff81111561034f5761034f610670565b6040519080825280601f01601f191660200182016040528015610379576020820181803683370190505b50905060208082019086860101610391828287610403565b509095945050505050565b81516000906103ac83600261065d565b11156103b757600080fd5b50016002015161ffff1690565b600060606103d3838587610459565b91509150935093915050565b81516000906103ef83602061065d565b11156103fa57600080fd5b50016020015190565b6020811061043b578151835261041a60208461065d565b925061042760208361065d565b915061043460208261060b565b9050610403565b905182516020929092036101000a6000190180199091169116179052565b60006060600085518551855188888860405160200161047d969594939291906106b6565b6040516020818303038152906040529050835167ffffffffffffffff8111156104a8576104a8610670565b6040519080825280601f01601f1916602001820160405280156104d2576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b60008083601f84011261050257600080fd5b50813567ffffffffffffffff81111561051a57600080fd5b60208301915083602082850101111561053257600080fd5b9250929050565b6000806000806000806060878903121561055257600080fd5b863567ffffffffffffffff8082111561056a57600080fd5b6105768a838b016104f0565b9098509650602089013591508082111561058f57600080fd5b61059b8a838b016104f0565b909650945060408901359150808211156105b457600080fd5b506105c189828a016104f0565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b61ffff818116838216019080821115610604576106046105d3565b5092915050565b81810381811115610314576103146105d3565b8183823760009101908152919050565b60006020828403121561064057600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b80820180821115610314576103146105d3565b634e487b7160e01b600052604160045260246000fd5b6000815160005b818110156106a7576020818501810151868301520161068d565b50600093019283525090919050565b86815285602082015284604082015260006106e66106e06106da6060850188610686565b86610686565b84610686565b9897505050505050505056fea264697066735822122081d54f6872821586c976d8d9aa106e2ea811afa445a713b0da099f753dd8e48364736f6c63430008110033",
    +  "contractName": "RSASHA256Algorithm",
    +  "sourceName": "contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol",
    +  "bytecode": "0x6080604052348015600f57600080fd5b50610afb8061001f6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046108bd565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102c89050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b9250610167610107826005610992565b61ffff9081169060059061011d9085168d6109ac565b61012791906109ac565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b9150610227565b6101b260058b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061035e9050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b925061022461020e826007610992565b61ffff9081169060079061011d9085168d6109ac565b91505b6102ba828488888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040516002925061027591508e908e906109bf565b602060405180830381855afa158015610292573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906102b591906109cf565b61037b565b9a9950505050505050505050565b60006102de836102d98460016109e8565b6103f3565b8282815181106102f0576102f06109fb565b016020015160f81c90505b92915050565b60608167ffffffffffffffff81111561031c5761031c610a2a565b6040519080825280601f01601f191660200182016040528015610346576020820181803683370190505b509050610357848483600086610448565b9392505050565b600061036f836102d98460026109e8565b50016020015160f01c90565b60008060006103c18787876040518060400160405280601381526020017f3031300d06096086480165030402010500042000000000000000000000000000815250610480565b915091508180156103e857506103e5602082516103de91906109ac565b82906106e5565b84145b979650505050505050565b81518111156104445781516040517f8a3c1cfb00000000000000000000000000000000000000000000000000000000815261043b918391600401918252602082015260400190565b60405180910390fd5b5050565b610456856102d983876109e8565b610464836102d983856109e8565b610479826020850101856020880101836106ff565b5050505050565b60006060600080610492888888610785565b915091508115806104a557508751815114155b156104b7576000935091506106dc9050565b806000815181106104ca576104ca6109fb565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615158061055857508060018151811061050c5761050c6109fb565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f010000000000000000000000000000000000000000000000000000000000000014155b1561056a576000935091506106dc9050565b60008551600f1461057c57602061057f565b60145b60ff169050600081835161059391906109ac565b905060008751826105a491906109ac565b9050836105b26001836109ac565b815181106105c2576105c26109fb565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016156105ff576000849650965050505050506106dc565b875161061390859083908b906000906107a0565b610628576000849650965050505050506106dc565b600060026106376001846109ac565b61064191906109ac565b9050600881101561065e57600085975097505050505050506106dc565b60025b61066c6001846109ac565b8110156106ce57858181518110610685576106856109fb565b01602001517fff00000000000000000000000000000000000000000000000000000000000000908116146106c65760008698509850505050505050506106dc565b600101610661565b506001975093955050505050505b94509492505050565b60006106f6836102d98460206109e8565b50016020015190565b5b601f81111561073e5781518352602092830192909101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001610700565b801561078057815183516001602084900360031b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161783525b505050565b600060606107948385876107c3565b91509150935093915050565b60006107ad84848461085a565b6107b887878561085a565b149695505050505050565b6000606060008551855185518888886040516020016107e796959493929190610a89565b6040516020818303038152906040529050835167ffffffffffffffff81111561081257610812610a2a565b6040519080825280601f01601f19166020018201604052801561083c576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b600061086a846102d984866109e8565b5091016020012090565b60008083601f84011261088657600080fd5b50813567ffffffffffffffff81111561089e57600080fd5b6020830191508360208285010111156108b657600080fd5b9250929050565b600080600080600080606087890312156108d657600080fd5b863567ffffffffffffffff8111156108ed57600080fd5b6108f989828a01610874565b909750955050602087013567ffffffffffffffff81111561091957600080fd5b61092589828a01610874565b909550935050604087013567ffffffffffffffff81111561094557600080fd5b61095189828a01610874565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff81811683821601908111156102fb576102fb610963565b818103818111156102fb576102fb610963565b8183823760009101908152919050565b6000602082840312156109e157600080fd5b5051919050565b808201808211156102fb576102fb610963565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000815160005b81811015610a7a5760208185018101518683015201610a60565b50600093019283525090919050565b8681528560208201528460408201526000610ab9610ab3610aad6060850188610a59565b86610a59565b84610a59565b9897505050505050505056fea2646970667358221220335ba623c7b8866af790ac308322c39a6ebbb7d4fae75897391e659f245c261264736f6c634300081a0033",
    +  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e3660046108bd565b610057565b604051901515815260200160405180910390f35b600060608060006100a260048b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506102c89050565b60ff169050801561016e576100f760058261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b9250610167610107826005610992565b61ffff9081169060059061011d9085168d6109ac565b61012791906109ac565b8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b9150610227565b6101b260058b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061035e9050565b90506101fe60078261ffff168c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506103019050565b925061022461020e826007610992565b61ffff9081169060079061011d9085168d6109ac565b91505b6102ba828488888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040516002925061027591508e908e906109bf565b602060405180830381855afa158015610292573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906102b591906109cf565b61037b565b9a9950505050505050505050565b60006102de836102d98460016109e8565b6103f3565b8282815181106102f0576102f06109fb565b016020015160f81c90505b92915050565b60608167ffffffffffffffff81111561031c5761031c610a2a565b6040519080825280601f01601f191660200182016040528015610346576020820181803683370190505b509050610357848483600086610448565b9392505050565b600061036f836102d98460026109e8565b50016020015160f01c90565b60008060006103c18787876040518060400160405280601381526020017f3031300d06096086480165030402010500042000000000000000000000000000815250610480565b915091508180156103e857506103e5602082516103de91906109ac565b82906106e5565b84145b979650505050505050565b81518111156104445781516040517f8a3c1cfb00000000000000000000000000000000000000000000000000000000815261043b918391600401918252602082015260400190565b60405180910390fd5b5050565b610456856102d983876109e8565b610464836102d983856109e8565b610479826020850101856020880101836106ff565b5050505050565b60006060600080610492888888610785565b915091508115806104a557508751815114155b156104b7576000935091506106dc9050565b806000815181106104ca576104ca6109fb565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615158061055857508060018151811061050c5761050c6109fb565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f010000000000000000000000000000000000000000000000000000000000000014155b1561056a576000935091506106dc9050565b60008551600f1461057c57602061057f565b60145b60ff169050600081835161059391906109ac565b905060008751826105a491906109ac565b9050836105b26001836109ac565b815181106105c2576105c26109fb565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016156105ff576000849650965050505050506106dc565b875161061390859083908b906000906107a0565b610628576000849650965050505050506106dc565b600060026106376001846109ac565b61064191906109ac565b9050600881101561065e57600085975097505050505050506106dc565b60025b61066c6001846109ac565b8110156106ce57858181518110610685576106856109fb565b01602001517fff00000000000000000000000000000000000000000000000000000000000000908116146106c65760008698509850505050505050506106dc565b600101610661565b506001975093955050505050505b94509492505050565b60006106f6836102d98460206109e8565b50016020015190565b5b601f81111561073e5781518352602092830192909101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001610700565b801561078057815183516001602084900360031b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161783525b505050565b600060606107948385876107c3565b91509150935093915050565b60006107ad84848461085a565b6107b887878561085a565b149695505050505050565b6000606060008551855185518888886040516020016107e796959493929190610a89565b6040516020818303038152906040529050835167ffffffffffffffff81111561081257610812610a2a565b6040519080825280601f01601f19166020018201604052801561083c576020820181803683370190505b50915083516020830182516020840160055afa925050935093915050565b600061086a846102d984866109e8565b5091016020012090565b60008083601f84011261088657600080fd5b50813567ffffffffffffffff81111561089e57600080fd5b6020830191508360208285010111156108b657600080fd5b9250929050565b600080600080600080606087890312156108d657600080fd5b863567ffffffffffffffff8111156108ed57600080fd5b6108f989828a01610874565b909750955050602087013567ffffffffffffffff81111561091957600080fd5b61092589828a01610874565b909550935050604087013567ffffffffffffffff81111561094557600080fd5b61095189828a01610874565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff81811683821601908111156102fb576102fb610963565b818103818111156102fb576102fb610963565b8183823760009101908152919050565b6000602082840312156109e157600080fd5b5051919050565b808201808211156102fb576102fb610963565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000815160005b81811015610a7a5760208185018101518683015201610a60565b50600093019283525090919050565b8681528560208201528460408201526000610ab9610ab3610aad6060850188610a59565b86610a59565b84610a59565b9897505050505050505056fea2646970667358221220335ba623c7b8866af790ac308322c39a6ebbb7d4fae75897391e659f245c261264736f6c634300081a0033",
    +  "linkReferences": {},
    +  "deployedLinkReferences": {},
    +  "immutableReferences": {},
    +  "inputSourceName": "project/contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol",
       "devdoc": {
         "details": "Implements the DNSSEC RSASHA256 algorithm.",
    +    "errors": {
    +      "OffsetOutOfBoundsError(uint256,uint256)": [
    +        {
    +          "details": "`offset` was beyond `length`.       Error selector: `0x8a3c1cfb`"
    +        }
    +      ]
    +    },
         "kind": "dev",
         "methods": {},
         "version": 1
       },
    +  "evm": {
    +    "gasEstimates": {
    +      "creation": {
    +        "codeDepositCost": "562200",
    +        "executionCost": "594",
    +        "totalCost": "562794"
    +      },
    +      "external": {
    +        "verify(bytes,bytes,bytes)": "infinite"
    +      }
    +    }
    +  },
    +  "metadata": "{\"compiler\":{\"version\":\"0.8.26+commit.8a97fa7a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements the DNSSEC RSASHA256 algorithm.\",\"errors\":{\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`.       Error selector: `0x8a3c1cfb`\"}]},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol\":\"RSASHA256Algorithm\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[\"project/:@ensdomains/solsha1/=npm/@ensdomains/solsha1@0.0.3/\"]},\"sources\":{\"project/contracts/dnssec-oracle/algorithms/Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/// @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\\ninterface Algorithm {\\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    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata signature\\n    ) external view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xbcbdc06d72b64903e733e7ddfbf59c35c984c3eb0022baacab12c97292cc13df\"},\"project/contracts/dnssec-oracle/algorithms/ModexpPrecompile.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary ModexpPrecompile {\\n    /// @dev Computes (base ^ exponent) % modulus over big numbers.\\n    function modexp(\\n        bytes memory base,\\n        bytes memory exponent,\\n        bytes memory modulus\\n    ) internal view returns (bool success, bytes memory output) {\\n        bytes memory input = abi.encodePacked(\\n            uint256(base.length),\\n            uint256(exponent.length),\\n            uint256(modulus.length),\\n            base,\\n            exponent,\\n            modulus\\n        );\\n\\n        output = new bytes(modulus.length);\\n\\n        assembly {\\n            success := staticcall(\\n                gas(),\\n                5,\\n                add(input, 32),\\n                mload(input),\\n                add(output, 32),\\n                mload(modulus)\\n            )\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x06457e4fc1eda1e2ba6ef08cb270983756e760bdeaa3155e1ca69a5f4bc5dd1f\"},\"project/contracts/dnssec-oracle/algorithms/RSAPKCS1Verify.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./RSAVerify.sol\\\";\\nimport \\\"../../utils/BytesUtils.sol\\\";\\n\\n/// @dev Library for PKCS#1 v1.5 signature verification\\nlibrary RSAPKCS1Verify {\\n    using BytesUtils for *;\\n\\n    /// @dev PKCS#1 v1.5 DigestInfo prefix for SHA-1\\n    bytes constant SHA1_DIGEST_INFO = hex\\\"3021300906052b0e03021a05000414\\\";\\n\\n    /// @dev PKCS#1 v1.5 DigestInfo prefix for SHA-256\\n    bytes constant SHA256_DIGEST_INFO = hex\\\"3031300d060960864801650304020105000420\\\";\\n\\n    /// @dev Verifies an RSA signature with PKCS#1 v1.5 padding for SHA-1\\n    function verifySHA1(\\n        bytes memory modulus,\\n        bytes memory exponent,\\n        bytes memory sig,\\n        bytes20 hash\\n    ) internal view returns (bool) {\\n        (bool ok, bytes memory result) = recoverAndVerify(modulus, exponent, sig, SHA1_DIGEST_INFO);\\n        return ok && hash == result.readBytes20(result.length - 20);\\n    }\\n\\n    /// @dev Verifies an RSA signature with PKCS#1 v1.5 padding for SHA-256\\n    function verifySHA256(\\n        bytes memory modulus,\\n        bytes memory exponent,\\n        bytes memory sig,\\n        bytes32 hash\\n    ) internal view returns (bool) {\\n        (bool ok, bytes memory result) = recoverAndVerify(modulus, exponent, sig, SHA256_DIGEST_INFO);\\n        return ok && hash == result.readBytes32(result.length - 32);\\n    }\\n\\n    /// @dev Recovers RSA signature and verifies PKCS#1 v1.5 structure\\n    /// Format: 0x00 0x01 [0xFF padding] 0x00 [DigestInfo] [Hash]\\n    /// https://datatracker.ietf.org/doc/html/rfc8017#section-9.2\\n    function recoverAndVerify(\\n        bytes memory modulus,\\n        bytes memory exponent,\\n        bytes memory sig,\\n        bytes memory digestInfo\\n    ) private view returns (bool, bytes memory) {\\n        (bool ok, bytes memory result) = RSAVerify.rsarecover(modulus, exponent, sig);\\n        if (!ok || result.length != modulus.length) {\\n            return (false, result);\\n        }\\n\\n        // Check leading bytes: 0x00 0x01\\n        if (result[0] != 0x00 || result[1] != 0x01) {\\n            return (false, result);\\n        }\\n\\n        // Calculate positions working backwards from the end\\n        uint256 hashLen = digestInfo.length == 15 ? 20 : 32;\\n        uint256 hashStart = result.length - hashLen;\\n        uint256 digestInfoStart = hashStart - digestInfo.length;\\n\\n        // Verify 0x00 separator before DigestInfo\\n        if (result[digestInfoStart - 1] != 0x00) {\\n            return (false, result);\\n        }\\n\\n        // Verify DigestInfo matches expected value\\n        if (!result.equals(digestInfoStart, digestInfo, 0, digestInfo.length)) {\\n            return (false, result);\\n        }\\n\\n        // Verify padding: all bytes from position 2 to separator must be 0xFF\\n        // Minimum 8 bytes of 0xFF padding required (RFC 3447)\\n        uint256 paddingLen = digestInfoStart - 1 - 2;\\n        if (paddingLen < 8) {\\n            return (false, result);\\n        }\\n        for (uint256 i = 2; i < digestInfoStart - 1; i++) {\\n            if (result[i] != 0xFF) {\\n                return (false, result);\\n            }\\n        }\\n\\n        return (true, result);\\n    }\\n}\\n\",\"keccak256\":\"0x92c872f6bb94670de46829d61122fcb0b0642dbd8e0e6fe31d2e8d387c890e87\"},\"project/contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"./RSAPKCS1Verify.sol\\\";\\nimport \\\"../../utils/BytesUtils.sol\\\";\\n\\n/// @dev Implements the DNSSEC RSASHA256 algorithm.\\ncontract RSASHA256Algorithm is Algorithm {\\n    using BytesUtils for *;\\n\\n    function verify(\\n        bytes calldata key,\\n        bytes calldata data,\\n        bytes calldata sig\\n    ) external view override returns (bool) {\\n        bytes memory exponent;\\n        bytes memory modulus;\\n\\n        uint16 exponentLen = uint16(key.readUint8(4));\\n        if (exponentLen != 0) {\\n            exponent = key.substring(5, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 5,\\n                key.length - exponentLen - 5\\n            );\\n        } else {\\n            exponentLen = key.readUint16(5);\\n            exponent = key.substring(7, exponentLen);\\n            modulus = key.substring(\\n                exponentLen + 7,\\n                key.length - exponentLen - 7\\n            );\\n        }\\n\\n        return RSAPKCS1Verify.verifySHA256(modulus, exponent, sig, sha256(data));\\n    }\\n}\\n\",\"keccak256\":\"0x7fcee47279521f12f45867173e778ccf575f3af26d880132927897bb1b12889e\"},\"project/contracts/dnssec-oracle/algorithms/RSAVerify.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./ModexpPrecompile.sol\\\";\\nimport \\\"../../utils/BytesUtils.sol\\\";\\n\\nlibrary RSAVerify {\\n    /// @dev Recovers the input data from an RSA signature, returning the result in S.\\n    /// @param N The RSA public modulus.\\n    /// @param E The RSA public exponent.\\n    /// @param S The signature to recover.\\n    /// @return True if the recovery succeeded.\\n    function rsarecover(\\n        bytes memory N,\\n        bytes memory E,\\n        bytes memory S\\n    ) internal view returns (bool, bytes memory) {\\n        return ModexpPrecompile.modexp(S, E, N);\\n    }\\n}\\n\",\"keccak256\":\"0x3de747c1a48c82031e79a35c6b844697e48c8d0549cb3475783b1447895ef8ab\"},\"project/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n    /// @dev `offset` was beyond `length`.\\n    ///       Error selector: `0x8a3c1cfb`\\n    error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n    /// @dev Assert `end` is not beyond the length of `v`.\\n    function _checkBound(bytes memory v, uint256 end) internal pure {\\n        if (end > v.length) {\\n            revert OffsetOutOfBoundsError(end, v.length);\\n        }\\n    }\\n\\n    /// @dev Compute `keccak256(v[off:off+len])`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @param len The number of bytes to hash.\\n    /// @return ret The corresponding hash.\\n    function keccak(\\n        bytes memory v,\\n        uint256 off,\\n        uint256 len\\n    ) internal pure returns (bytes32 ret) {\\n        _checkBound(v, off + len);\\n        assembly (\\\"memory-safe\\\") {\\n            ret := keccak256(add(add(v, 32), off), len)\\n        }\\n    }\\n\\n    /// @dev Lexicographically compare two byte strings.\\n    /// @param vA The first bytes to compare.\\n    /// @param vB The second bytes to compare.\\n    /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n    function compare(\\n        bytes memory vA,\\n        bytes memory vB\\n    ) internal pure returns (int256) {\\n        return compare(vA, 0, vA.length, vB, 0, vB.length);\\n    }\\n\\n    /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n    /// @param vA The first bytes.\\n    /// @param offA The offset of the first bytes.\\n    /// @param lenA The length of the first bytes.\\n    /// @param vB The second bytes.\\n    /// @param offB The offset of the second bytes.\\n    /// @param lenB The length of the second bytes.\\n    /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n    function compare(\\n        bytes memory vA,\\n        uint256 offA,\\n        uint256 lenA,\\n        bytes memory vB,\\n        uint256 offB,\\n        uint256 lenB\\n    ) internal pure returns (int256) {\\n        _checkBound(vA, offA + lenA);\\n        _checkBound(vB, offB + lenB);\\n        unchecked {\\n            uint256 ptrA = LibMem.ptr(vA) + offA;\\n            uint256 ptrB = LibMem.ptr(vB) + offB;\\n            uint256 shortest = lenA < lenB ? lenA : lenB;\\n            for (uint256 i; i < shortest; i += 32) {\\n                uint256 a = LibMem.load(ptrA + i);\\n                uint256 b = LibMem.load(ptrB + i);\\n                if (a != b) {\\n                    uint256 rest = shortest - i;\\n                    if (rest < 32) {\\n                        rest = (32 - rest) << 3; // bits to drop\\n                        a >>= rest; // shift out the\\n                        b >>= rest; // irrelevant bits\\n                    }\\n                    if (a < b) {\\n                        return -1;\\n                    } else if (a > b) {\\n                        return 1;\\n                    }\\n                }\\n            }\\n        }\\n        return int256(lenA) - int256(lenB);\\n    }\\n\\n    /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n    /// @param vA The first bytes.\\n    /// @param offA The offset into the first bytes.\\n    /// @param vB The second bytes.\\n    /// @param offB The offset into the second bytes.\\n    /// @param len The number of bytes to compare.\\n    /// @return True if the byte ranges are equal.\\n    function equals(\\n        bytes memory vA,\\n        uint256 offA,\\n        bytes memory vB,\\n        uint256 offB,\\n        uint256 len\\n    ) internal pure returns (bool) {\\n        return keccak(vA, offA, len) == keccak(vB, offB, len);\\n    }\\n\\n    /// @dev Determine if `a[offA:] == b[offB:]`.\\n    /// @param vA The first bytes.\\n    /// @param offA The offset into the first bytes.\\n    /// @param vB The second bytes.\\n    /// @param offB The offset into the second bytes.\\n    /// @return True if the byte ranges are equal.\\n    function equals(\\n        bytes memory vA,\\n        uint256 offA,\\n        bytes memory vB,\\n        uint256 offB\\n    ) internal pure returns (bool) {\\n        _checkBound(vA, offA);\\n        _checkBound(vB, offB);\\n        unchecked {\\n            return\\n                keccak(vA, offA, vA.length - offA) ==\\n                keccak(vB, offB, vB.length - offB);\\n        }\\n    }\\n\\n    /// @dev Determine if `a[offA:] == b`.\\n    /// @param vA The first bytes.\\n    /// @param offA The offset into the first bytes.\\n    /// @param vB The second bytes.\\n    /// @return True if the byte ranges are equal.\\n    function equals(\\n        bytes memory vA,\\n        uint256 offA,\\n        bytes memory vB\\n    ) internal pure returns (bool) {\\n        return\\n            vA.length == offA + vB.length &&\\n            keccak(vA, offA, vB.length) == keccak256(vB);\\n    }\\n\\n    /// @dev Determine if `a == b`.\\n    /// @param vA The first bytes.\\n    /// @param vB The second bytes.\\n    /// @return True if the bytes are equal.\\n    function equals(\\n        bytes memory vA,\\n        bytes memory vB\\n    ) internal pure returns (bool) {\\n        return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n    }\\n\\n    /// @dev Returns `uint8(v[off])`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @return The corresponding `uint8`.\\n    function readUint8(\\n        bytes memory v,\\n        uint256 off\\n    ) internal pure returns (uint8) {\\n        _checkBound(v, off + 1);\\n        unchecked {\\n            return uint8(v[off]);\\n        }\\n    }\\n\\n    /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @return ret The corresponding `uint16`.\\n    function readUint16(\\n        bytes memory v,\\n        uint256 off\\n    ) internal pure returns (uint16 ret) {\\n        _checkBound(v, off + 2);\\n        assembly (\\\"memory-safe\\\") {\\n            ret := shr(240, mload(add(add(v, 32), off)))\\n        }\\n    }\\n\\n    /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @return ret The corresponding `uint32`.\\n    function readUint32(\\n        bytes memory v,\\n        uint256 off\\n    ) internal pure returns (uint32 ret) {\\n        _checkBound(v, off + 4);\\n        assembly (\\\"memory-safe\\\") {\\n            ret := shr(224, mload(add(add(v, 32), off)))\\n        }\\n    }\\n\\n    /// @dev Returns `bytes20(v[off:off+20])`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @return ret The corresponding `bytes20`.\\n    function readBytes20(\\n        bytes memory v,\\n        uint256 off\\n    ) internal pure returns (bytes20 ret) {\\n        _checkBound(v, off + 20);\\n        assembly (\\\"memory-safe\\\") {\\n            ret := shl(96, mload(add(add(v, 20), off)))\\n        }\\n    }\\n\\n    /// @dev Returns `bytes32(v[off:off+32])`.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @return ret The corresponding `bytes32`.\\n    function readBytes32(\\n        bytes memory v,\\n        uint256 off\\n    ) internal pure returns (bytes32 ret) {\\n        _checkBound(v, off + 32);\\n        assembly (\\\"memory-safe\\\") {\\n            ret := mload(add(add(v, 32), off))\\n        }\\n    }\\n\\n    /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n    ///      Accepts 0-32 bytes or reverts.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @param len The number of bytes.\\n    /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n    function readBytesN(\\n        bytes memory v,\\n        uint256 off,\\n        uint256 len\\n    ) internal pure returns (bytes32 ret) {\\n        assert(len <= 32);\\n        _checkBound(v, off + len);\\n        assembly (\\\"memory-safe\\\") {\\n            let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00><NxFF>\\n            ret := and(mload(add(add(v, 32), off)), not(mask))\\n        }\\n    }\\n\\n    /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n    /// @param vSrc The source bytes.\\n    /// @param offSrc The offset into the source to begin the copy.\\n    /// @param vDst The destination bytes.\\n    /// @param offDst The offset into the destination to place the copy.\\n    /// @param len The number of bytes to copy.\\n    function copyBytes(\\n        bytes memory vSrc,\\n        uint256 offSrc,\\n        bytes memory vDst,\\n        uint256 offDst,\\n        uint256 len\\n    ) internal pure {\\n        _checkBound(vSrc, offSrc + len);\\n        _checkBound(vDst, offDst + len);\\n        unchecked {\\n            LibMem.copy(\\n                LibMem.ptr(vDst) + offDst,\\n                LibMem.ptr(vSrc) + offSrc,\\n                len\\n            );\\n        }\\n    }\\n\\n    /// @dev Copies a substring into a new byte string.\\n    /// @param vSrc The byte string to copy from.\\n    /// @param off The offset to start copying at.\\n    /// @param len The number of bytes to copy.\\n    /// @return vDst The copied substring.\\n    function substring(\\n        bytes memory vSrc,\\n        uint256 off,\\n        uint256 len\\n    ) internal pure returns (bytes memory vDst) {\\n        vDst = new bytes(len);\\n        copyBytes(vSrc, off, vDst, 0, len);\\n    }\\n\\n    /// @dev Find the first occurrence of `needle`.\\n    /// @param v The bytes to search.\\n    /// @param off The offset to start searching.\\n    /// @param len The number of bytes to search.\\n    /// @param needle The byte to search for.\\n    /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n    function find(\\n        bytes memory v,\\n        uint256 off,\\n        uint256 len,\\n        bytes1 needle\\n    ) internal pure returns (uint256) {\\n        for (uint256 end = off + len; off < end; off++) {\\n            if (v[off] == needle) {\\n                return off;\\n            }\\n        }\\n        return type(uint256).max;\\n    }\\n\\n    /// @dev Returns `true` if word contains a zero byte.\\n    function hasZeroByte(uint256 word) internal pure returns (bool) {\\n        unchecked {\\n            return\\n                ((~word &\\n                    (word -\\n                        0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n                    0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n                0;\\n        }\\n    }\\n\\n    /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n    /// @param v The source bytes.\\n    /// @param off The offset into the source.\\n    /// @param len The number of bytes to search.\\n    /// @param needle The byte to search for.\\n    /// @return found `true` if `needle` was found.\\n    function includes(\\n        bytes memory v,\\n        uint256 off,\\n        uint256 len,\\n        bytes1 needle\\n    ) internal pure returns (bool found) {\\n        _checkBound(v, off + len);\\n        unchecked {\\n            uint256 wide = uint8(needle);\\n            wide |= wide << 8;\\n            wide |= wide << 16;\\n            wide |= wide << 32;\\n            wide |= wide << 64;\\n            wide |= wide << 128; // broadcast byte across word\\n            off += LibMem.ptr(v);\\n            len += off;\\n            while (off < len) {\\n                uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n                off += 32;\\n                if (hasZeroByte(word)) {\\n                    return\\n                        off <= len ||\\n                        hasZeroByte(\\n                            word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n                        );\\n                }\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n    /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n    ///      Equivalent to `mcopy()`.\\n    ///\\n    /// @param src The source memory offset.\\n    /// @param dst The destination memory offset.\\n    /// @param len The number of bytes to copy.\\n    function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n        assembly {\\n            // Copy word-length chunks while possible\\n            // prettier-ignore\\n            for {} gt(len, 31) {} {\\n                mstore(dst, mload(src))\\n                dst := add(dst, 32)\\n                src := add(src, 32)\\n                len := sub(len, 32)\\n            }\\n            // Copy remaining bytes\\n            if len {\\n                let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n                let wSrc := and(mload(src), not(mask))\\n                let wDst := and(mload(dst), mask)\\n                mstore(dst, or(wSrc, wDst))\\n            }\\n        }\\n    }\\n\\n    /// @dev Convert bytes to a memory offset.\\n    ///\\n    /// @param v The bytes to convert.\\n    ///\\n    /// @return ret The corresponding memory offset.\\n    function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n        assembly {\\n            ret := add(v, 32)\\n        }\\n    }\\n\\n    /// @dev Read word at memory offset.\\n    ///\\n    /// @param src The memory offset.\\n    ///\\n    /// @return ret The read word.\\n    function load(uint256 src) internal pure returns (uint256 ret) {\\n        assembly {\\n            ret := mload(src)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"}},\"version\":1}",
    +  "storageLayout": {
    +    "storage": [],
    +    "types": null
    +  },
       "userdoc": {
         "kind": "user",
         "methods": {},
         "version": 1
       },
    -  "storageLayout": {
    -    "storage": [],
    -    "types": null
    +  "argsData": "0x",
    +  "transaction": {
    +    "hash": "0xc76f028db051778f2d4bef00e89600039558ca6d1b157caef35dbe424647988e",
    +    "nonce": "0x8",
    +    "origin": "0xceed1f4f358e635da87704305c884b4550e82ecb"
    +  },
    +  "receipt": {
    +    "blockHash": "0x57e7728d718bda0f46e1681ff82388f8aa8fcc846625cda369205dad4457789b",
    +    "blockNumber": "0x9dacb1",
    +    "transactionIndex": "0xb"
       }
     }
    \ No newline at end of file
    
  • test/dnssec-oracle/TestRSAForgedSignature.test.ts+93 0 added
    @@ -0,0 +1,93 @@
    +import hre from 'hardhat'
    +import { sha256, toHex, concat } from 'viem'
    +
    +/**
    + * Bleichenbacher RSA Signature Forgery Test
    + *
    + * Demonstrates that RSASHA256Algorithm.verify() rejects forged signatures
    + * for RSA keys with low exponent (e=3) due to proper PKCS#1 v1.5 validation.
    + */
    +
    +const connection = await hre.network.connect()
    +
    +// ============================================================================
    +// Crypto helpers (attack-specific, can't reuse from codebase)
    +// ============================================================================
    +
    +/** Hensel lifting: find x where x³ ≡ h (mod 2^n) */
    +function cubeRootMod2n(h: bigint, n = 256): bigint {
    +  if (h % 2n === 0n) throw new Error('h must be odd')
    +  let x = 1n
    +  for (let i = 1; i < n; i++) {
    +    const mod = 2n ** BigInt(i + 1)
    +    const fx = (x ** 3n - h) % mod
    +    const fpx = (3n * x * x) % mod
    +    const fpxInv = modInverse(fpx, mod)
    +    x = ((x - fx * fpxInv) % mod + mod) % mod
    +  }
    +  return x
    +}
    +
    +/** Extended Euclidean algorithm for modular inverse */
    +function modInverse(a: bigint, m: bigint): bigint {
    +  let [old_r, r] = [a, m]
    +  let [old_s, s] = [1n, 0n]
    +  while (r !== 0n) {
    +    const q = old_r / r
    +    ;[old_r, r] = [r, old_r - q * r]
    +    ;[old_s, s] = [s, old_s - q * s]
    +  }
    +  return ((old_s % m) + m) % m
    +}
    +
    +/** Convert bigint to big-endian bytes */
    +function bigIntToBytes(n: bigint, len: number): Uint8Array {
    +  const hex = n.toString(16).padStart(len * 2, '0')
    +  const bytes = new Uint8Array(len)
    +  for (let i = 0; i < len; i++) {
    +    bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16)
    +  }
    +  return bytes
    +}
    +
    +// ============================================================================
    +// Test
    +// ============================================================================
    +
    +describe('RSA Signature Forgery (Bleichenbacher Attack)', () => {
    +  it('should reject forged signature for e=3 key', async () => {
    +    const algorithm = await connection.viem.deployContract('RSASHA256Algorithm', [])
    +
    +    // RSA key with e=3 (2048-bit modulus) - mimics .cc/.name KSK
    +    const modulusBytes = 256
    +    const modulusInt = BigInt('0x' + 'ff'.repeat(255) + '01')
    +    const modulus = bigIntToBytes(modulusInt, modulusBytes)
    +    const exponent = 3
    +
    +    // Build DNSKEY format: flags(2) + protocol(1) + algo(1) + expLen(1) + exp + modulus
    +    const key = concat([
    +      new Uint8Array([0x01, 0x01, 0x03, 0x08, 0x01, exponent]),
    +      modulus,
    +    ])
    +
    +    // Find data whose hash is odd (required for Hensel lifting)
    +    let data: Uint8Array
    +    let h: bigint = 0n
    +    for (let nonce = 0; nonce < 10000; nonce++) {
    +      data = new Uint8Array([nonce & 0xff])
    +      h = BigInt(sha256(data))
    +      if (h % 2n === 1n) break
    +    }
    +
    +    const forgedSig = bigIntToBytes(cubeRootMod2n(h), modulusBytes)
    +
    +    const isValid = await algorithm.read.verify([
    +      toHex(key),
    +      toHex(data!),
    +      toHex(forgedSig),
    +    ])
    +
    +    console.log('Forged signature rejected:', !isValid)
    +    expect(isValid).toBe(false)
    +  })
    +})
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.