From 07281e048eb4db4636e3b9e0b0943010640c4cd6 Mon Sep 17 00:00:00 2001 From: Jeff Lau Date: Tue, 15 Aug 2023 12:04:37 +0800 Subject: [PATCH] Deploy dnssec registrar to Sepolia --- README.md | 10 +- deployments/sepolia/DNSRegistrar.json | 447 ++++++++++++++++ deployments/sepolia/DNSSECImpl.json | 530 +++++++++++++++++++ deployments/sepolia/DummyAlgorithm.json | 71 +++ deployments/sepolia/DummyDigest.json | 66 +++ deployments/sepolia/OffchainDNSResolver.json | 210 ++++++++ deployments/sepolia/P256SHA256Algorithm.json | 82 +++ deployments/sepolia/RSASHA1Algorithm.json | 71 +++ deployments/sepolia/RSASHA256Algorithm.json | 71 +++ deployments/sepolia/SHA1Digest.json | 77 +++ deployments/sepolia/SHA256Digest.json | 76 +++ deployments/sepolia/TLDPublicSuffixList.json | 61 +++ 12 files changed, 1767 insertions(+), 5 deletions(-) create mode 100644 deployments/sepolia/DNSRegistrar.json create mode 100644 deployments/sepolia/DNSSECImpl.json create mode 100644 deployments/sepolia/DummyAlgorithm.json create mode 100644 deployments/sepolia/DummyDigest.json create mode 100644 deployments/sepolia/OffchainDNSResolver.json create mode 100644 deployments/sepolia/P256SHA256Algorithm.json create mode 100644 deployments/sepolia/RSASHA1Algorithm.json create mode 100644 deployments/sepolia/RSASHA256Algorithm.json create mode 100644 deployments/sepolia/SHA1Digest.json create mode 100644 deployments/sepolia/SHA256Digest.json create mode 100644 deployments/sepolia/TLDPublicSuffixList.json diff --git a/README.md b/README.md index c43dbf11..0daf34e8 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,7 @@ yarn pub 6. Have the tagged commit audited if necessary 7. If changes are required, make the changes and then once ready for review create another GitHub release with an incremented RC value `v1.2.3-RC0` -> `v.1.2.3-RC1`. Repeat as necessary. 8. Deploy to testnet. Commit build artifacts to `feature` branch. You now MUST merge this branch into `staging` branch. -9. Create GitHub release of the form `v1.2.3-testnet` from the commit that has the new deployment artifacts. +9. Create GitHub release of the form `v1.2.3-testnet` from the commit that has the new deployment artifacts. 10. If any further changes are needed, you can either make them on the existing feature branch that is in sync or create a new branch, and follow steps 1 -> 9. Repeat as necessary. 11. Make Deployment to mainnet from `staging`. Commit build artifacts. You now MUST merge this branch into `main`. 12. Create GitHub release of the form `v1.2.3-mainnet` from the commit that has the new deployment artifacts. @@ -192,11 +192,11 @@ yarn pub - `staging` branch and `main` branch should start off in sync - `staging` is intended to be a practice `main`. Only code that is intended to be released to `main` can be merged to `staging`. Consequently: - - Feature branches will be long-lived - - Feature branches must be kept in sync with `staging` - - Audits are conducted on feature branches + - Feature branches will be long-lived + - Feature branches must be kept in sync with `staging` + - Audits are conducted on feature branches - All code that is on `staging` and `main` should be deployed to testnet and mainnet respectively i.e. these branches should not have any undeployed code - It is preferable to not edit the same file on different feature branches. - Code on `staging` and `main` will always be a subset of what is deployed, as smart contracts cannot be undeployed. - Release candidates, `staging` and `main` branch are subject to our bug bounty -- Releases follow semantic versioning and should contain a description of changes with developers being the intended audience \ No newline at end of file +- Releases follow semantic versioning and should contain a description of changes with developers being the intended audience diff --git a/deployments/sepolia/DNSRegistrar.json b/deployments/sepolia/DNSRegistrar.json new file mode 100644 index 00000000..466f5299 --- /dev/null +++ b/deployments/sepolia/DNSRegistrar.json @@ -0,0 +1,447 @@ +{ + "address": "0x537625B0D7901FD20C57850d61580Bf1624Ef146", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_previousRegistrar", + "type": "address" + }, + { + "internalType": "address", + "name": "_resolver", + "type": "address" + }, + { + "internalType": "contract DNSSEC", + "name": "_dnssec", + "type": "address" + }, + { + "internalType": "contract PublicSuffixList", + "name": "_suffixes", + "type": "address" + }, + { + "internalType": "contract ENS", + "name": "_ens", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "InvalidPublicSuffix", + "type": "error" + }, + { + "inputs": [], + "name": "NoOwnerRecordFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "PermissionDenied", + "type": "error" + }, + { + "inputs": [], + "name": "PreconditionNotMet", + "type": "error" + }, + { + "inputs": [], + "name": "StaleProof", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "dnsname", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "inception", + "type": "uint32" + } + ], + "name": "Claim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "suffixes", + "type": "address" + } + ], + "name": "NewPublicSuffixList", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "domain", + "type": "bytes" + } + ], + "name": "enableNode", + "outputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "ens", + "outputs": [ + { + "internalType": "contract ENS", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "inceptions", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract DNSSEC", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "previousRegistrar", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "rrset", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "sig", + "type": "bytes" + } + ], + "internalType": "struct DNSSEC.RRSetWithSignature[]", + "name": "input", + "type": "tuple[]" + } + ], + "name": "proveAndClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "rrset", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "sig", + "type": "bytes" + } + ], + "internalType": "struct DNSSEC.RRSetWithSignature[]", + "name": "input", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "proveAndClaimWithResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract PublicSuffixList", + "name": "_suffixes", + "type": "address" + } + ], + "name": "setPublicSuffixList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "suffixes", + "outputs": [ + { + "internalType": "contract PublicSuffixList", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xb83bb66b77ec57bce2d2019bf3851a1e6daa853cbce02de1b8403174fbe338fc", + "receipt": { + "to": null, + "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8", + "contractAddress": "0x537625B0D7901FD20C57850d61580Bf1624Ef146", + "transactionIndex": 97, + "gasUsed": "1924139", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000", + "blockHash": "0xa10cf59bdef6dae6471ac87297f53abc305290cfd0c0b25478f7e5f3a7d641e7", + "transactionHash": "0xb83bb66b77ec57bce2d2019bf3851a1e6daa853cbce02de1b8403174fbe338fc", + "logs": [ + { + "transactionIndex": 97, + "blockNumber": 4091758, + "transactionHash": "0xb83bb66b77ec57bce2d2019bf3851a1e6daa853cbce02de1b8403174fbe338fc", + "address": "0x537625B0D7901FD20C57850d61580Bf1624Ef146", + "topics": [ + "0x9176b7f47e4504df5e5516c99d90d82ac7cbd49cc77e7f22ba2ac2f2e3a3eba8" + ], + "data": "0x00000000000000000000000041b1a43af05e484b36b1322af1f798970e8a8ce8", + "logIndex": 199, + "blockHash": "0xa10cf59bdef6dae6471ac87297f53abc305290cfd0c0b25478f7e5f3a7d641e7" + } + ], + "blockNumber": 4091758, + "cumulativeGasUsed": "19551588", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + "0xEaDF0008EaAF803805eDb39F0d95CBdE003a2470", + "0x7b3ada1c8f012bae747cf99d6cbbf70d040b84cf", + "0x41b1a43Af05e484B36b1322Af1F798970E8a8ce8", + "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" + ], + "numDeployments": 1, + "solcInputHash": "e04502f562d98d0455f6c1c453418cdd", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_previousRegistrar\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_resolver\",\"type\":\"address\"},{\"internalType\":\"contract DNSSEC\",\"name\":\"_dnssec\",\"type\":\"address\"},{\"internalType\":\"contract PublicSuffixList\",\"name\":\"_suffixes\",\"type\":\"address\"},{\"internalType\":\"contract ENS\",\"name\":\"_ens\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"InvalidPublicSuffix\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoOwnerRecordFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"PermissionDenied\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PreconditionNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleProof\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"dnsname\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"inception\",\"type\":\"uint32\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"suffixes\",\"type\":\"address\"}],\"name\":\"NewPublicSuffixList\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"domain\",\"type\":\"bytes\"}],\"name\":\"enableNode\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ens\",\"outputs\":[{\"internalType\":\"contract ENS\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"inceptions\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract DNSSEC\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousRegistrar\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature[]\",\"name\":\"input\",\"type\":\"tuple[]\"}],\"name\":\"proveAndClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature[]\",\"name\":\"input\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"proveAndClaimWithResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract PublicSuffixList\",\"name\":\"_suffixes\",\"type\":\"address\"}],\"name\":\"setPublicSuffixList\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"suffixes\",\"outputs\":[{\"internalType\":\"contract PublicSuffixList\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"An ENS registrar that allows the owner of a DNS name to claim the corresponding name in ENS.\",\"kind\":\"dev\",\"methods\":{\"proveAndClaim(bytes,(bytes,bytes)[])\":{\"details\":\"Submits proofs to the DNSSEC oracle, then claims a name using those proofs.\",\"params\":{\"input\":\"A chain of signed DNS RRSETs ending with a text record.\",\"name\":\"The name to claim, in DNS wire format.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnsregistrar/DNSRegistrar.sol\":\"DNSRegistrar\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"@ensdomains/buffer/contracts/Buffer.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-2-Clause\\npragma solidity ^0.8.4;\\n\\n/**\\n* @dev A library for working with mutable byte buffers in Solidity.\\n*\\n* Byte buffers are mutable and expandable, and provide a variety of primitives\\n* for appending to them. At any time you can fetch a bytes object containing the\\n* current contents of the buffer. The bytes object should not be stored between\\n* operations, as it may change due to resizing of the buffer.\\n*/\\nlibrary Buffer {\\n /**\\n * @dev Represents a mutable buffer. Buffers have a current value (buf) and\\n * a capacity. The capacity may be longer than the current value, in\\n * which case it can be extended without the need to allocate more memory.\\n */\\n struct buffer {\\n bytes buf;\\n uint capacity;\\n }\\n\\n /**\\n * @dev Initializes a buffer with an initial capacity.\\n * @param buf The buffer to initialize.\\n * @param capacity The number of bytes of space to allocate the buffer.\\n * @return The buffer, for chaining.\\n */\\n function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {\\n if (capacity % 32 != 0) {\\n capacity += 32 - (capacity % 32);\\n }\\n // Allocate space for the buffer data\\n buf.capacity = capacity;\\n assembly {\\n let ptr := mload(0x40)\\n mstore(buf, ptr)\\n mstore(ptr, 0)\\n let fpm := add(32, add(ptr, capacity))\\n if lt(fpm, ptr) {\\n revert(0, 0)\\n }\\n mstore(0x40, fpm)\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Initializes a new buffer from an existing bytes object.\\n * Changes to the buffer may mutate the original value.\\n * @param b The bytes object to initialize the buffer with.\\n * @return A new buffer.\\n */\\n function fromBytes(bytes memory b) internal pure returns(buffer memory) {\\n buffer memory buf;\\n buf.buf = b;\\n buf.capacity = b.length;\\n return buf;\\n }\\n\\n function resize(buffer memory buf, uint capacity) private pure {\\n bytes memory oldbuf = buf.buf;\\n init(buf, capacity);\\n append(buf, oldbuf);\\n }\\n\\n /**\\n * @dev Sets buffer length to 0.\\n * @param buf The buffer to truncate.\\n * @return The original buffer, for chaining..\\n */\\n function truncate(buffer memory buf) internal pure returns (buffer memory) {\\n assembly {\\n let bufptr := mload(buf)\\n mstore(bufptr, 0)\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to copy.\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) {\\n require(len <= data.length);\\n\\n uint off = buf.buf.length;\\n uint newCapacity = off + len;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n uint dest;\\n uint src;\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Length of existing buffer data\\n let buflen := mload(bufptr)\\n // Start address = buffer address + offset + sizeof(buffer length)\\n dest := add(add(bufptr, 32), off)\\n // Update buffer length if we're extending it\\n if gt(newCapacity, buflen) {\\n mstore(bufptr, newCapacity)\\n }\\n src := add(data, 32)\\n }\\n\\n // Copy word-length chunks while possible\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n // Copy remaining bytes\\n unchecked {\\n uint mask = (256 ** (32 - len)) - 1;\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n\\n return buf;\\n }\\n\\n /**\\n * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\\n return append(buf, data, data.length);\\n }\\n\\n /**\\n * @dev Appends a byte to the buffer. Resizes if doing so would exceed the\\n * capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint offPlusOne = off + 1;\\n if (off >= buf.capacity) {\\n resize(buf, offPlusOne * 2);\\n }\\n\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + off\\n let dest := add(add(bufptr, off), 32)\\n mstore8(dest, data)\\n // Update buffer length if we extended it\\n if gt(offPlusOne, mload(bufptr)) {\\n mstore(bufptr, offPlusOne)\\n }\\n }\\n\\n return buf;\\n }\\n\\n /**\\n * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would\\n * exceed the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to write (left-aligned).\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint newCapacity = len + off;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n unchecked {\\n uint mask = (256 ** len) - 1;\\n // Right-align data\\n data = data >> (8 * (32 - len));\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + newCapacity\\n let dest := add(bufptr, newCapacity)\\n mstore(dest, or(and(mload(dest), not(mask)), data))\\n // Update buffer length if we extended it\\n if gt(newCapacity, mload(bufptr)) {\\n mstore(bufptr, newCapacity)\\n }\\n }\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chhaining.\\n */\\n function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {\\n return append(buf, bytes32(data), 20);\\n }\\n\\n /**\\n * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {\\n return append(buf, data, 32);\\n }\\n\\n /**\\n * @dev Appends a byte to the end of the buffer. Resizes if doing so would\\n * exceed the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to write (right-aligned).\\n * @return The original buffer.\\n */\\n function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint newCapacity = len + off;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n uint mask = (256 ** len) - 1;\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + newCapacity\\n let dest := add(bufptr, newCapacity)\\n mstore(dest, or(and(mload(dest), not(mask)), data))\\n // Update buffer length if we extended it\\n if gt(newCapacity, mload(bufptr)) {\\n mstore(bufptr, newCapacity)\\n }\\n }\\n return buf;\\n }\\n}\\n\",\"keccak256\":\"0xd6dd3b0b327288f8e1b711a609f4040fea602e2ad4bba9febdf2f33b4e56eb0c\",\"license\":\"BSD-2-Clause\"},\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/dnsregistrar/DNSClaimChecker.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../dnssec-oracle/DNSSEC.sol\\\";\\nimport \\\"../dnssec-oracle/BytesUtils.sol\\\";\\nimport \\\"../dnssec-oracle/RRUtils.sol\\\";\\nimport \\\"../utils/HexUtils.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\nlibrary DNSClaimChecker {\\n using BytesUtils for bytes;\\n using HexUtils for bytes;\\n using RRUtils for *;\\n using Buffer for Buffer.buffer;\\n\\n uint16 constant CLASS_INET = 1;\\n uint16 constant TYPE_TXT = 16;\\n\\n function getOwnerAddress(\\n bytes memory name,\\n bytes memory data\\n ) internal pure returns (address, bool) {\\n // Add \\\"_ens.\\\" to the front of the name.\\n Buffer.buffer memory buf;\\n buf.init(name.length + 5);\\n buf.append(\\\"\\\\x04_ens\\\");\\n buf.append(name);\\n\\n for (\\n RRUtils.RRIterator memory iter = data.iterateRRs(0);\\n !iter.done();\\n iter.next()\\n ) {\\n if (iter.name().compareNames(buf.buf) != 0) continue;\\n bool found;\\n address addr;\\n (addr, found) = parseRR(data, iter.rdataOffset, iter.nextOffset);\\n if (found) {\\n return (addr, true);\\n }\\n }\\n\\n return (address(0x0), false);\\n }\\n\\n function parseRR(\\n bytes memory rdata,\\n uint256 idx,\\n uint256 endIdx\\n ) internal pure returns (address, bool) {\\n while (idx < endIdx) {\\n uint256 len = rdata.readUint8(idx);\\n idx += 1;\\n\\n bool found;\\n address addr;\\n (addr, found) = parseString(rdata, idx, len);\\n\\n if (found) return (addr, true);\\n idx += len;\\n }\\n\\n return (address(0x0), false);\\n }\\n\\n function parseString(\\n bytes memory str,\\n uint256 idx,\\n uint256 len\\n ) internal pure returns (address, bool) {\\n // TODO: More robust parsing that handles whitespace and multiple key/value pairs\\n if (str.readUint32(idx) != 0x613d3078) return (address(0x0), false); // 0x613d3078 == 'a=0x'\\n return str.hexToAddress(idx + 4, idx + len);\\n }\\n}\\n\",\"keccak256\":\"0x8269236f2a421e278e3e9642d2a5c29545993e8a4586a2592067155822d59069\",\"license\":\"MIT\"},\"contracts/dnsregistrar/DNSRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\nimport \\\"../dnssec-oracle/BytesUtils.sol\\\";\\nimport \\\"../dnssec-oracle/DNSSEC.sol\\\";\\nimport \\\"../dnssec-oracle/RRUtils.sol\\\";\\nimport \\\"../registry/ENSRegistry.sol\\\";\\nimport \\\"../root/Root.sol\\\";\\nimport \\\"../resolvers/profiles/AddrResolver.sol\\\";\\nimport \\\"./DNSClaimChecker.sol\\\";\\nimport \\\"./PublicSuffixList.sol\\\";\\nimport \\\"./IDNSRegistrar.sol\\\";\\n\\n/**\\n * @dev An ENS registrar that allows the owner of a DNS name to claim the\\n * corresponding name in ENS.\\n */\\ncontract DNSRegistrar is IDNSRegistrar, IERC165 {\\n using BytesUtils for bytes;\\n using Buffer for Buffer.buffer;\\n using RRUtils for *;\\n\\n ENS public immutable ens;\\n DNSSEC public immutable oracle;\\n PublicSuffixList public suffixes;\\n address public immutable previousRegistrar;\\n address public immutable resolver;\\n // A mapping of the most recent signatures seen for each claimed domain.\\n mapping(bytes32 => uint32) public inceptions;\\n\\n error NoOwnerRecordFound();\\n error PermissionDenied(address caller, address owner);\\n error PreconditionNotMet();\\n error StaleProof();\\n error InvalidPublicSuffix(bytes name);\\n\\n struct OwnerRecord {\\n bytes name;\\n address owner;\\n address resolver;\\n uint64 ttl;\\n }\\n\\n event Claim(\\n bytes32 indexed node,\\n address indexed owner,\\n bytes dnsname,\\n uint32 inception\\n );\\n event NewPublicSuffixList(address suffixes);\\n\\n constructor(\\n address _previousRegistrar,\\n address _resolver,\\n DNSSEC _dnssec,\\n PublicSuffixList _suffixes,\\n ENS _ens\\n ) {\\n previousRegistrar = _previousRegistrar;\\n resolver = _resolver;\\n oracle = _dnssec;\\n suffixes = _suffixes;\\n emit NewPublicSuffixList(address(suffixes));\\n ens = _ens;\\n }\\n\\n /**\\n * @dev This contract's owner-only functions can be invoked by the owner of the ENS root.\\n */\\n modifier onlyOwner() {\\n Root root = Root(ens.owner(bytes32(0)));\\n address owner = root.owner();\\n require(msg.sender == owner);\\n _;\\n }\\n\\n function setPublicSuffixList(PublicSuffixList _suffixes) public onlyOwner {\\n suffixes = _suffixes;\\n emit NewPublicSuffixList(address(suffixes));\\n }\\n\\n /**\\n * @dev Submits proofs to the DNSSEC oracle, then claims a name using those proofs.\\n * @param name The name to claim, in DNS wire format.\\n * @param input A chain of signed DNS RRSETs ending with a text record.\\n */\\n function proveAndClaim(\\n bytes memory name,\\n DNSSEC.RRSetWithSignature[] memory input\\n ) public override {\\n (bytes32 rootNode, bytes32 labelHash, address addr) = _claim(\\n name,\\n input\\n );\\n ens.setSubnodeOwner(rootNode, labelHash, addr);\\n }\\n\\n function proveAndClaimWithResolver(\\n bytes memory name,\\n DNSSEC.RRSetWithSignature[] memory input,\\n address resolver,\\n address addr\\n ) public override {\\n (bytes32 rootNode, bytes32 labelHash, address owner) = _claim(\\n name,\\n input\\n );\\n if (msg.sender != owner) {\\n revert PermissionDenied(msg.sender, owner);\\n }\\n ens.setSubnodeRecord(rootNode, labelHash, owner, resolver, 0);\\n if (addr != address(0)) {\\n if (resolver == address(0)) {\\n revert PreconditionNotMet();\\n }\\n bytes32 node = keccak256(abi.encodePacked(rootNode, labelHash));\\n // Set the resolver record\\n AddrResolver(resolver).setAddr(node, addr);\\n }\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) external pure override returns (bool) {\\n return\\n interfaceID == type(IERC165).interfaceId ||\\n interfaceID == type(IDNSRegistrar).interfaceId;\\n }\\n\\n function _claim(\\n bytes memory name,\\n DNSSEC.RRSetWithSignature[] memory input\\n ) internal returns (bytes32 parentNode, bytes32 labelHash, address addr) {\\n (bytes memory data, uint32 inception) = oracle.verifyRRSet(input);\\n\\n // Get the first label\\n uint256 labelLen = name.readUint8(0);\\n labelHash = name.keccak(1, labelLen);\\n\\n bytes memory parentName = name.substring(\\n labelLen + 1,\\n name.length - labelLen - 1\\n );\\n\\n // Make sure the parent name is enabled\\n parentNode = enableNode(parentName);\\n\\n bytes32 node = keccak256(abi.encodePacked(parentNode, labelHash));\\n if (!RRUtils.serialNumberGte(inception, inceptions[node])) {\\n revert StaleProof();\\n }\\n inceptions[node] = inception;\\n\\n bool found;\\n (addr, found) = DNSClaimChecker.getOwnerAddress(name, data);\\n if (!found) {\\n revert NoOwnerRecordFound();\\n }\\n\\n emit Claim(node, addr, name, inception);\\n }\\n\\n function enableNode(bytes memory domain) public returns (bytes32 node) {\\n // Name must be in the public suffix list.\\n if (!suffixes.isPublicSuffix(domain)) {\\n revert InvalidPublicSuffix(domain);\\n }\\n return _enableNode(domain, 0);\\n }\\n\\n function _enableNode(\\n bytes memory domain,\\n uint256 offset\\n ) internal returns (bytes32 node) {\\n uint256 len = domain.readUint8(offset);\\n if (len == 0) {\\n return bytes32(0);\\n }\\n\\n bytes32 parentNode = _enableNode(domain, offset + len + 1);\\n bytes32 label = domain.keccak(offset + 1, len);\\n node = keccak256(abi.encodePacked(parentNode, label));\\n address owner = ens.owner(node);\\n if (owner == address(0) || owner == previousRegistrar) {\\n if (parentNode == bytes32(0)) {\\n Root root = Root(ens.owner(bytes32(0)));\\n root.setSubnodeOwner(label, address(this));\\n ens.setResolver(node, resolver);\\n } else {\\n ens.setSubnodeRecord(\\n parentNode,\\n label,\\n address(this),\\n resolver,\\n 0\\n );\\n }\\n } else if (owner != address(this)) {\\n revert PreconditionNotMet();\\n }\\n return node;\\n }\\n}\\n\",\"keccak256\":\"0x9140c28eee7f8dff1cc0a2380e9b57db3203c8c0d187245ab3595f4e4cbdebce\",\"license\":\"MIT\"},\"contracts/dnsregistrar/IDNSRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../dnssec-oracle/DNSSEC.sol\\\";\\n\\ninterface IDNSRegistrar {\\n function proveAndClaim(\\n bytes memory name,\\n DNSSEC.RRSetWithSignature[] memory input\\n ) external;\\n\\n function proveAndClaimWithResolver(\\n bytes memory name,\\n DNSSEC.RRSetWithSignature[] memory input,\\n address resolver,\\n address addr\\n ) external;\\n}\\n\",\"keccak256\":\"0xcf6607fe4918cabb1c4c2130597dd9cc0f63492564b05de60496eb46873a73b7\",\"license\":\"MIT\"},\"contracts/dnsregistrar/PublicSuffixList.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\ninterface PublicSuffixList {\\n function isPublicSuffix(bytes calldata name) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x12158ba8838ee2b1ebb0178a52d2f4d54dcc68282d569226e62afc2b0dccbbac\"},\"contracts/dnssec-oracle/BytesUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary BytesUtils {\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /*\\n * @dev Returns the keccak-256 hash of a byte range.\\n * @param self The byte string to hash.\\n * @param offset The position to start hashing at.\\n * @param len The number of bytes to hash.\\n * @return The hash of the byte range.\\n */\\n function keccak(\\n bytes memory self,\\n uint256 offset,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n require(offset + len <= self.length);\\n assembly {\\n ret := keccak256(add(add(self, 32), offset), len)\\n }\\n }\\n\\n /*\\n * @dev Returns a positive number if `other` comes lexicographically after\\n * `self`, a negative number if it comes before, or zero if the\\n * contents of the two bytes are equal.\\n * @param self The first bytes to compare.\\n * @param other The second bytes to compare.\\n * @return The result of the comparison.\\n */\\n function compare(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (int256) {\\n return compare(self, 0, self.length, other, 0, other.length);\\n }\\n\\n /*\\n * @dev Returns a positive number if `other` comes lexicographically after\\n * `self`, a negative number if it comes before, or zero if the\\n * contents of the two bytes are equal. Comparison is done per-rune,\\n * on unicode codepoints.\\n * @param self The first bytes to compare.\\n * @param offset The offset of self.\\n * @param len The length of self.\\n * @param other The second bytes to compare.\\n * @param otheroffset The offset of the other string.\\n * @param otherlen The length of the other string.\\n * @return The result of the comparison.\\n */\\n function compare(\\n bytes memory self,\\n uint256 offset,\\n uint256 len,\\n bytes memory other,\\n uint256 otheroffset,\\n uint256 otherlen\\n ) internal pure returns (int256) {\\n if (offset + len > self.length) {\\n revert OffsetOutOfBoundsError(offset + len, self.length);\\n }\\n if (otheroffset + otherlen > other.length) {\\n revert OffsetOutOfBoundsError(otheroffset + otherlen, other.length);\\n }\\n\\n uint256 shortest = len;\\n if (otherlen < len) shortest = otherlen;\\n\\n uint256 selfptr;\\n uint256 otherptr;\\n\\n assembly {\\n selfptr := add(self, add(offset, 32))\\n otherptr := add(other, add(otheroffset, 32))\\n }\\n for (uint256 idx = 0; idx < shortest; idx += 32) {\\n uint256 a;\\n uint256 b;\\n assembly {\\n a := mload(selfptr)\\n b := mload(otherptr)\\n }\\n if (a != b) {\\n // Mask out irrelevant bytes and check again\\n uint256 mask;\\n if (shortest - idx >= 32) {\\n mask = type(uint256).max;\\n } else {\\n mask = ~(2 ** (8 * (idx + 32 - shortest)) - 1);\\n }\\n int256 diff = int256(a & mask) - int256(b & mask);\\n if (diff != 0) return diff;\\n }\\n selfptr += 32;\\n otherptr += 32;\\n }\\n\\n return int256(len) - int256(otherlen);\\n }\\n\\n /*\\n * @dev Returns true if the two byte ranges are equal.\\n * @param self The first byte range to compare.\\n * @param offset The offset into the first byte range.\\n * @param other The second byte range to compare.\\n * @param otherOffset The offset into the second byte range.\\n * @param len The number of bytes to compare\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n uint256 offset,\\n bytes memory other,\\n uint256 otherOffset,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(self, offset, len) == keccak(other, otherOffset, len);\\n }\\n\\n /*\\n * @dev Returns true if the two byte ranges are equal with offsets.\\n * @param self The first byte range to compare.\\n * @param offset The offset into the first byte range.\\n * @param other The second byte range to compare.\\n * @param otherOffset The offset into the second byte range.\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n uint256 offset,\\n bytes memory other,\\n uint256 otherOffset\\n ) internal pure returns (bool) {\\n return\\n keccak(self, offset, self.length - offset) ==\\n keccak(other, otherOffset, other.length - otherOffset);\\n }\\n\\n /*\\n * @dev Compares a range of 'self' to all of 'other' and returns True iff\\n * they are equal.\\n * @param self The first byte range to compare.\\n * @param offset The offset into the first byte range.\\n * @param other The second byte range to compare.\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n uint256 offset,\\n bytes memory other\\n ) internal pure returns (bool) {\\n return\\n self.length == offset + other.length &&\\n equals(self, offset, other, 0, other.length);\\n }\\n\\n /*\\n * @dev Returns true if the two byte ranges are equal.\\n * @param self The first byte range to compare.\\n * @param other The second byte range to compare.\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (bool) {\\n return\\n self.length == other.length &&\\n equals(self, 0, other, 0, self.length);\\n }\\n\\n /*\\n * @dev Returns the 8-bit number at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 8 bits of the string, interpreted as an integer.\\n */\\n function readUint8(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (uint8 ret) {\\n return uint8(self[idx]);\\n }\\n\\n /*\\n * @dev Returns the 16-bit number at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 16 bits of the string, interpreted as an integer.\\n */\\n function readUint16(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (uint16 ret) {\\n require(idx + 2 <= self.length);\\n assembly {\\n ret := and(mload(add(add(self, 2), idx)), 0xFFFF)\\n }\\n }\\n\\n /*\\n * @dev Returns the 32-bit number at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 32 bits of the string, interpreted as an integer.\\n */\\n function readUint32(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (uint32 ret) {\\n require(idx + 4 <= self.length);\\n assembly {\\n ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF)\\n }\\n }\\n\\n /*\\n * @dev Returns the 32 byte value at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 32 bytes of the string.\\n */\\n function readBytes32(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (bytes32 ret) {\\n require(idx + 32 <= self.length);\\n assembly {\\n ret := mload(add(add(self, 32), idx))\\n }\\n }\\n\\n /*\\n * @dev Returns the 32 byte value at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 32 bytes of the string.\\n */\\n function readBytes20(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (bytes20 ret) {\\n require(idx + 20 <= self.length);\\n assembly {\\n ret := and(\\n mload(add(add(self, 32), idx)),\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000\\n )\\n }\\n }\\n\\n /*\\n * @dev Returns the n byte value at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes.\\n * @param len The number of bytes.\\n * @return The specified 32 bytes of the string.\\n */\\n function readBytesN(\\n bytes memory self,\\n uint256 idx,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n require(len <= 32);\\n require(idx + len <= self.length);\\n assembly {\\n let mask := not(sub(exp(256, sub(32, len)), 1))\\n ret := and(mload(add(add(self, 32), idx)), mask)\\n }\\n }\\n\\n function memcpy(uint256 dest, uint256 src, uint256 len) private pure {\\n // Copy word-length chunks while possible\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n // Copy remaining bytes\\n unchecked {\\n uint256 mask = (256 ** (32 - len)) - 1;\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n }\\n\\n /*\\n * @dev Copies a substring into a new byte string.\\n * @param self The byte string to copy from.\\n * @param offset The offset to start copying at.\\n * @param len The number of bytes to copy.\\n */\\n function substring(\\n bytes memory self,\\n uint256 offset,\\n uint256 len\\n ) internal pure returns (bytes memory) {\\n require(offset + len <= self.length);\\n\\n bytes memory ret = new bytes(len);\\n uint256 dest;\\n uint256 src;\\n\\n assembly {\\n dest := add(ret, 32)\\n src := add(add(self, 32), offset)\\n }\\n memcpy(dest, src, len);\\n\\n return ret;\\n }\\n\\n // Maps characters from 0x30 to 0x7A to their base32 values.\\n // 0xFF represents invalid characters in that range.\\n bytes constant base32HexTable =\\n hex\\\"00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\\\";\\n\\n /**\\n * @dev Decodes unpadded base32 data of up to one word in length.\\n * @param self The data to decode.\\n * @param off Offset into the string to start at.\\n * @param len Number of characters to decode.\\n * @return The decoded data, left aligned.\\n */\\n function base32HexDecodeWord(\\n bytes memory self,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32) {\\n require(len <= 52);\\n\\n uint256 ret = 0;\\n uint8 decoded;\\n for (uint256 i = 0; i < len; i++) {\\n bytes1 char = self[off + i];\\n require(char >= 0x30 && char <= 0x7A);\\n decoded = uint8(base32HexTable[uint256(uint8(char)) - 0x30]);\\n require(decoded <= 0x20);\\n if (i == len - 1) {\\n break;\\n }\\n ret = (ret << 5) | decoded;\\n }\\n\\n uint256 bitlen = len * 5;\\n if (len % 8 == 0) {\\n // Multiple of 8 characters, no padding\\n ret = (ret << 5) | decoded;\\n } else if (len % 8 == 2) {\\n // Two extra characters - 1 byte\\n ret = (ret << 3) | (decoded >> 2);\\n bitlen -= 2;\\n } else if (len % 8 == 4) {\\n // Four extra characters - 2 bytes\\n ret = (ret << 1) | (decoded >> 4);\\n bitlen -= 4;\\n } else if (len % 8 == 5) {\\n // Five extra characters - 3 bytes\\n ret = (ret << 4) | (decoded >> 1);\\n bitlen -= 1;\\n } else if (len % 8 == 7) {\\n // Seven extra characters - 4 bytes\\n ret = (ret << 2) | (decoded >> 3);\\n bitlen -= 3;\\n } else {\\n revert();\\n }\\n\\n return bytes32(ret << (256 - bitlen));\\n }\\n\\n /**\\n * @dev Finds the first occurrence of the byte `needle` in `self`.\\n * @param self The string to search\\n * @param off The offset to start searching at\\n * @param len The number of bytes to search\\n * @param needle The byte to search for\\n * @return The offset of `needle` in `self`, or 2**256-1 if it was not found.\\n */\\n function find(\\n bytes memory self,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 idx = off; idx < off + len; idx++) {\\n if (self[idx] == needle) {\\n return idx;\\n }\\n }\\n return type(uint256).max;\\n }\\n}\\n\",\"keccak256\":\"0x4f10902639b85a17ae10745264feff322e793bfb1bc130a9a90efa7dda47c6cc\"},\"contracts/dnssec-oracle/DNSSEC.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\npragma experimental ABIEncoderV2;\\n\\nabstract contract DNSSEC {\\n bytes public anchors;\\n\\n struct RRSetWithSignature {\\n bytes rrset;\\n bytes sig;\\n }\\n\\n event AlgorithmUpdated(uint8 id, address addr);\\n event DigestUpdated(uint8 id, address addr);\\n\\n function verifyRRSet(\\n RRSetWithSignature[] memory input\\n ) external view virtual returns (bytes memory rrs, uint32 inception);\\n\\n function verifyRRSet(\\n RRSetWithSignature[] memory input,\\n uint256 now\\n ) public view virtual returns (bytes memory rrs, uint32 inception);\\n}\\n\",\"keccak256\":\"0xee6a236a59e5db8418c98ee4640a91987d26533c02d305cc6c7a37a3ac4ee907\",\"license\":\"MIT\"},\"contracts/dnssec-oracle/RRUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./BytesUtils.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\n/**\\n * @dev RRUtils is a library that provides utilities for parsing DNS resource records.\\n */\\nlibrary RRUtils {\\n using BytesUtils for *;\\n using Buffer for *;\\n\\n /**\\n * @dev Returns the number of bytes in the DNS name at 'offset' in 'self'.\\n * @param self The byte array to read a name from.\\n * @param offset The offset to start reading at.\\n * @return The length of the DNS name at 'offset', in bytes.\\n */\\n function nameLength(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (uint256) {\\n uint256 idx = offset;\\n while (true) {\\n assert(idx < self.length);\\n uint256 labelLen = self.readUint8(idx);\\n idx += labelLen + 1;\\n if (labelLen == 0) {\\n break;\\n }\\n }\\n return idx - offset;\\n }\\n\\n /**\\n * @dev Returns a DNS format name at the specified offset of self.\\n * @param self The byte array to read a name from.\\n * @param offset The offset to start reading at.\\n * @return ret The name.\\n */\\n function readName(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (bytes memory ret) {\\n uint256 len = nameLength(self, offset);\\n return self.substring(offset, len);\\n }\\n\\n /**\\n * @dev Returns the number of labels in the DNS name at 'offset' in 'self'.\\n * @param self The byte array to read a name from.\\n * @param offset The offset to start reading at.\\n * @return The number of labels in the DNS name at 'offset', in bytes.\\n */\\n function labelCount(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (uint256) {\\n uint256 count = 0;\\n while (true) {\\n assert(offset < self.length);\\n uint256 labelLen = self.readUint8(offset);\\n offset += labelLen + 1;\\n if (labelLen == 0) {\\n break;\\n }\\n count += 1;\\n }\\n return count;\\n }\\n\\n uint256 constant RRSIG_TYPE = 0;\\n uint256 constant RRSIG_ALGORITHM = 2;\\n uint256 constant RRSIG_LABELS = 3;\\n uint256 constant RRSIG_TTL = 4;\\n uint256 constant RRSIG_EXPIRATION = 8;\\n uint256 constant RRSIG_INCEPTION = 12;\\n uint256 constant RRSIG_KEY_TAG = 16;\\n uint256 constant RRSIG_SIGNER_NAME = 18;\\n\\n struct SignedSet {\\n uint16 typeCovered;\\n uint8 algorithm;\\n uint8 labels;\\n uint32 ttl;\\n uint32 expiration;\\n uint32 inception;\\n uint16 keytag;\\n bytes signerName;\\n bytes data;\\n bytes name;\\n }\\n\\n function readSignedSet(\\n bytes memory data\\n ) internal pure returns (SignedSet memory self) {\\n self.typeCovered = data.readUint16(RRSIG_TYPE);\\n self.algorithm = data.readUint8(RRSIG_ALGORITHM);\\n self.labels = data.readUint8(RRSIG_LABELS);\\n self.ttl = data.readUint32(RRSIG_TTL);\\n self.expiration = data.readUint32(RRSIG_EXPIRATION);\\n self.inception = data.readUint32(RRSIG_INCEPTION);\\n self.keytag = data.readUint16(RRSIG_KEY_TAG);\\n self.signerName = readName(data, RRSIG_SIGNER_NAME);\\n self.data = data.substring(\\n RRSIG_SIGNER_NAME + self.signerName.length,\\n data.length - RRSIG_SIGNER_NAME - self.signerName.length\\n );\\n }\\n\\n function rrs(\\n SignedSet memory rrset\\n ) internal pure returns (RRIterator memory) {\\n return iterateRRs(rrset.data, 0);\\n }\\n\\n /**\\n * @dev An iterator over resource records.\\n */\\n struct RRIterator {\\n bytes data;\\n uint256 offset;\\n uint16 dnstype;\\n uint16 class;\\n uint32 ttl;\\n uint256 rdataOffset;\\n uint256 nextOffset;\\n }\\n\\n /**\\n * @dev Begins iterating over resource records.\\n * @param self The byte string to read from.\\n * @param offset The offset to start reading at.\\n * @return ret An iterator object.\\n */\\n function iterateRRs(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (RRIterator memory ret) {\\n ret.data = self;\\n ret.nextOffset = offset;\\n next(ret);\\n }\\n\\n /**\\n * @dev Returns true iff there are more RRs to iterate.\\n * @param iter The iterator to check.\\n * @return True iff the iterator has finished.\\n */\\n function done(RRIterator memory iter) internal pure returns (bool) {\\n return iter.offset >= iter.data.length;\\n }\\n\\n /**\\n * @dev Moves the iterator to the next resource record.\\n * @param iter The iterator to advance.\\n */\\n function next(RRIterator memory iter) internal pure {\\n iter.offset = iter.nextOffset;\\n if (iter.offset >= iter.data.length) {\\n return;\\n }\\n\\n // Skip the name\\n uint256 off = iter.offset + nameLength(iter.data, iter.offset);\\n\\n // Read type, class, and ttl\\n iter.dnstype = iter.data.readUint16(off);\\n off += 2;\\n iter.class = iter.data.readUint16(off);\\n off += 2;\\n iter.ttl = iter.data.readUint32(off);\\n off += 4;\\n\\n // Read the rdata\\n uint256 rdataLength = iter.data.readUint16(off);\\n off += 2;\\n iter.rdataOffset = off;\\n iter.nextOffset = off + rdataLength;\\n }\\n\\n /**\\n * @dev Returns the name of the current record.\\n * @param iter The iterator.\\n * @return A new bytes object containing the owner name from the RR.\\n */\\n function name(RRIterator memory iter) internal pure returns (bytes memory) {\\n return\\n iter.data.substring(\\n iter.offset,\\n nameLength(iter.data, iter.offset)\\n );\\n }\\n\\n /**\\n * @dev Returns the rdata portion of the current record.\\n * @param iter The iterator.\\n * @return A new bytes object containing the RR's RDATA.\\n */\\n function rdata(\\n RRIterator memory iter\\n ) internal pure returns (bytes memory) {\\n return\\n iter.data.substring(\\n iter.rdataOffset,\\n iter.nextOffset - iter.rdataOffset\\n );\\n }\\n\\n uint256 constant DNSKEY_FLAGS = 0;\\n uint256 constant DNSKEY_PROTOCOL = 2;\\n uint256 constant DNSKEY_ALGORITHM = 3;\\n uint256 constant DNSKEY_PUBKEY = 4;\\n\\n struct DNSKEY {\\n uint16 flags;\\n uint8 protocol;\\n uint8 algorithm;\\n bytes publicKey;\\n }\\n\\n function readDNSKEY(\\n bytes memory data,\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (DNSKEY memory self) {\\n self.flags = data.readUint16(offset + DNSKEY_FLAGS);\\n self.protocol = data.readUint8(offset + DNSKEY_PROTOCOL);\\n self.algorithm = data.readUint8(offset + DNSKEY_ALGORITHM);\\n self.publicKey = data.substring(\\n offset + DNSKEY_PUBKEY,\\n length - DNSKEY_PUBKEY\\n );\\n }\\n\\n uint256 constant DS_KEY_TAG = 0;\\n uint256 constant DS_ALGORITHM = 2;\\n uint256 constant DS_DIGEST_TYPE = 3;\\n uint256 constant DS_DIGEST = 4;\\n\\n struct DS {\\n uint16 keytag;\\n uint8 algorithm;\\n uint8 digestType;\\n bytes digest;\\n }\\n\\n function readDS(\\n bytes memory data,\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (DS memory self) {\\n self.keytag = data.readUint16(offset + DS_KEY_TAG);\\n self.algorithm = data.readUint8(offset + DS_ALGORITHM);\\n self.digestType = data.readUint8(offset + DS_DIGEST_TYPE);\\n self.digest = data.substring(offset + DS_DIGEST, length - DS_DIGEST);\\n }\\n\\n function isSubdomainOf(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (bool) {\\n uint256 off = 0;\\n uint256 counts = labelCount(self, 0);\\n uint256 othercounts = labelCount(other, 0);\\n\\n while (counts > othercounts) {\\n off = progress(self, off);\\n counts--;\\n }\\n\\n return self.equals(off, other, 0);\\n }\\n\\n function compareNames(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (int256) {\\n if (self.equals(other)) {\\n return 0;\\n }\\n\\n uint256 off;\\n uint256 otheroff;\\n uint256 prevoff;\\n uint256 otherprevoff;\\n uint256 counts = labelCount(self, 0);\\n uint256 othercounts = labelCount(other, 0);\\n\\n // Keep removing labels from the front of the name until both names are equal length\\n while (counts > othercounts) {\\n prevoff = off;\\n off = progress(self, off);\\n counts--;\\n }\\n\\n while (othercounts > counts) {\\n otherprevoff = otheroff;\\n otheroff = progress(other, otheroff);\\n othercounts--;\\n }\\n\\n // Compare the last nonequal labels to each other\\n while (counts > 0 && !self.equals(off, other, otheroff)) {\\n prevoff = off;\\n off = progress(self, off);\\n otherprevoff = otheroff;\\n otheroff = progress(other, otheroff);\\n counts -= 1;\\n }\\n\\n if (off == 0) {\\n return -1;\\n }\\n if (otheroff == 0) {\\n return 1;\\n }\\n\\n return\\n self.compare(\\n prevoff + 1,\\n self.readUint8(prevoff),\\n other,\\n otherprevoff + 1,\\n other.readUint8(otherprevoff)\\n );\\n }\\n\\n /**\\n * @dev Compares two serial numbers using RFC1982 serial number math.\\n */\\n function serialNumberGte(\\n uint32 i1,\\n uint32 i2\\n ) internal pure returns (bool) {\\n unchecked {\\n return int32(i1) - int32(i2) >= 0;\\n }\\n }\\n\\n function progress(\\n bytes memory body,\\n uint256 off\\n ) internal pure returns (uint256) {\\n return off + 1 + body.readUint8(off);\\n }\\n\\n /**\\n * @dev Computes the keytag for a chunk of data.\\n * @param data The data to compute a keytag for.\\n * @return The computed key tag.\\n */\\n function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n /* This function probably deserves some explanation.\\n * The DNSSEC keytag function is a checksum that relies on summing up individual bytes\\n * from the input string, with some mild bitshifting. Here's a Naive solidity implementation:\\n *\\n * function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n * uint ac;\\n * for (uint i = 0; i < data.length; i++) {\\n * ac += i & 1 == 0 ? uint16(data.readUint8(i)) << 8 : data.readUint8(i);\\n * }\\n * return uint16(ac + (ac >> 16));\\n * }\\n *\\n * The EVM, with its 256 bit words, is exceedingly inefficient at doing byte-by-byte operations;\\n * the code above, on reasonable length inputs, consumes over 100k gas. But we can make the EVM's\\n * large words work in our favour.\\n *\\n * The code below works by treating the input as a series of 256 bit words. It first masks out\\n * even and odd bytes from each input word, adding them to two separate accumulators `ac1` and `ac2`.\\n * The bytes are separated by empty bytes, so as long as no individual sum exceeds 2^16-1, we're\\n * effectively summing 16 different numbers with each EVM ADD opcode.\\n *\\n * Once it's added up all the inputs, it has to add all the 16 bit values in `ac1` and `ac2` together.\\n * It does this using the same trick - mask out every other value, shift to align them, add them together.\\n * After the first addition on both accumulators, there's enough room to add the two accumulators together,\\n * and the remaining sums can be done just on ac1.\\n */\\n unchecked {\\n require(data.length <= 8192, \\\"Long keys not permitted\\\");\\n uint256 ac1;\\n uint256 ac2;\\n for (uint256 i = 0; i < data.length + 31; i += 32) {\\n uint256 word;\\n assembly {\\n word := mload(add(add(data, 32), i))\\n }\\n if (i + 32 > data.length) {\\n uint256 unused = 256 - (data.length - i) * 8;\\n word = (word >> unused) << unused;\\n }\\n ac1 +=\\n (word &\\n 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >>\\n 8;\\n ac2 += (word &\\n 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF);\\n }\\n ac1 =\\n (ac1 &\\n 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n ((ac1 &\\n 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n 16);\\n ac2 =\\n (ac2 &\\n 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n ((ac2 &\\n 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n 16);\\n ac1 = (ac1 << 8) + ac2;\\n ac1 =\\n (ac1 &\\n 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) +\\n ((ac1 &\\n 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >>\\n 32);\\n ac1 =\\n (ac1 &\\n 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) +\\n ((ac1 &\\n 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >>\\n 64);\\n ac1 =\\n (ac1 &\\n 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +\\n (ac1 >> 128);\\n ac1 += (ac1 >> 16) & 0xFFFF;\\n return uint16(ac1);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x4dd68a6efd7c38f6b0e95ca0c056ecb74f88583da650b1a8639e6e78be36fede\"},\"contracts/registry/ENS.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x7cb1158c7d268b63de1468e28e2711b28d686e2628ddb22da2149cd93ddeafda\"},\"contracts/registry/ENSRegistry.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\nimport \\\"./ENS.sol\\\";\\n\\n/**\\n * The ENS registry contract.\\n */\\ncontract ENSRegistry is ENS {\\n struct Record {\\n address owner;\\n address resolver;\\n uint64 ttl;\\n }\\n\\n mapping(bytes32 => Record) records;\\n mapping(address => mapping(address => bool)) operators;\\n\\n // Permits modifications only by the owner of the specified node.\\n modifier authorised(bytes32 node) {\\n address owner = records[node].owner;\\n require(owner == msg.sender || operators[owner][msg.sender]);\\n _;\\n }\\n\\n /**\\n * @dev Constructs a new ENS registry.\\n */\\n constructor() public {\\n records[0x0].owner = msg.sender;\\n }\\n\\n /**\\n * @dev Sets the record for a node.\\n * @param node The node to update.\\n * @param owner The address of the new owner.\\n * @param resolver The address of the resolver.\\n * @param ttl The TTL in seconds.\\n */\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external virtual override {\\n setOwner(node, owner);\\n _setResolverAndTTL(node, resolver, ttl);\\n }\\n\\n /**\\n * @dev Sets the record for a subnode.\\n * @param node The parent node.\\n * @param label The hash of the label specifying the subnode.\\n * @param owner The address of the new owner.\\n * @param resolver The address of the resolver.\\n * @param ttl The TTL in seconds.\\n */\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external virtual override {\\n bytes32 subnode = setSubnodeOwner(node, label, owner);\\n _setResolverAndTTL(subnode, resolver, ttl);\\n }\\n\\n /**\\n * @dev Transfers ownership of a node to a new address. May only be called by the current owner of the node.\\n * @param node The node to transfer ownership of.\\n * @param owner The address of the new owner.\\n */\\n function setOwner(\\n bytes32 node,\\n address owner\\n ) public virtual override authorised(node) {\\n _setOwner(node, owner);\\n emit Transfer(node, owner);\\n }\\n\\n /**\\n * @dev Transfers ownership of a subnode keccak256(node, label) to a new address. May only be called by the owner of the parent node.\\n * @param node The parent node.\\n * @param label The hash of the label specifying the subnode.\\n * @param owner The address of the new owner.\\n */\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) public virtual override authorised(node) returns (bytes32) {\\n bytes32 subnode = keccak256(abi.encodePacked(node, label));\\n _setOwner(subnode, owner);\\n emit NewOwner(node, label, owner);\\n return subnode;\\n }\\n\\n /**\\n * @dev Sets the resolver address for the specified node.\\n * @param node The node to update.\\n * @param resolver The address of the resolver.\\n */\\n function setResolver(\\n bytes32 node,\\n address resolver\\n ) public virtual override authorised(node) {\\n emit NewResolver(node, resolver);\\n records[node].resolver = resolver;\\n }\\n\\n /**\\n * @dev Sets the TTL for the specified node.\\n * @param node The node to update.\\n * @param ttl The TTL in seconds.\\n */\\n function setTTL(\\n bytes32 node,\\n uint64 ttl\\n ) public virtual override authorised(node) {\\n emit NewTTL(node, ttl);\\n records[node].ttl = ttl;\\n }\\n\\n /**\\n * @dev Enable or disable approval for a third party (\\\"operator\\\") to manage\\n * all of `msg.sender`'s ENS records. Emits the ApprovalForAll event.\\n * @param operator Address to add to the set of authorized operators.\\n * @param approved True if the operator is approved, false to revoke approval.\\n */\\n function setApprovalForAll(\\n address operator,\\n bool approved\\n ) external virtual override {\\n operators[msg.sender][operator] = approved;\\n emit ApprovalForAll(msg.sender, operator, approved);\\n }\\n\\n /**\\n * @dev Returns the address that owns the specified node.\\n * @param node The specified node.\\n * @return address of the owner.\\n */\\n function owner(\\n bytes32 node\\n ) public view virtual override returns (address) {\\n address addr = records[node].owner;\\n if (addr == address(this)) {\\n return address(0x0);\\n }\\n\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address of the resolver for the specified node.\\n * @param node The specified node.\\n * @return address of the resolver.\\n */\\n function resolver(\\n bytes32 node\\n ) public view virtual override returns (address) {\\n return records[node].resolver;\\n }\\n\\n /**\\n * @dev Returns the TTL of a node, and any records associated with it.\\n * @param node The specified node.\\n * @return ttl of the node.\\n */\\n function ttl(bytes32 node) public view virtual override returns (uint64) {\\n return records[node].ttl;\\n }\\n\\n /**\\n * @dev Returns whether a record has been imported to the registry.\\n * @param node The specified node.\\n * @return Bool if record exists\\n */\\n function recordExists(\\n bytes32 node\\n ) public view virtual override returns (bool) {\\n return records[node].owner != address(0x0);\\n }\\n\\n /**\\n * @dev Query if an address is an authorized operator for another address.\\n * @param owner The address that owns the records.\\n * @param operator The address that acts on behalf of the owner.\\n * @return True if `operator` is an approved operator for `owner`, false otherwise.\\n */\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view virtual override returns (bool) {\\n return operators[owner][operator];\\n }\\n\\n function _setOwner(bytes32 node, address owner) internal virtual {\\n records[node].owner = owner;\\n }\\n\\n function _setResolverAndTTL(\\n bytes32 node,\\n address resolver,\\n uint64 ttl\\n ) internal {\\n if (resolver != records[node].resolver) {\\n records[node].resolver = resolver;\\n emit NewResolver(node, resolver);\\n }\\n\\n if (ttl != records[node].ttl) {\\n records[node].ttl = ttl;\\n emit NewTTL(node, ttl);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa7a7a64fb980e521c991415e416fd4106a42f892479805e1daa51ecb0e2e5198\"},\"contracts/resolvers/ResolverBase.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"./profiles/IVersionableResolver.sol\\\";\\n\\nabstract contract ResolverBase is ERC165, IVersionableResolver {\\n mapping(bytes32 => uint64) public recordVersions;\\n\\n function isAuthorised(bytes32 node) internal view virtual returns (bool);\\n\\n modifier authorised(bytes32 node) {\\n require(isAuthorised(node));\\n _;\\n }\\n\\n /**\\n * Increments the record version associated with an ENS node.\\n * May only be called by the owner of that node in the ENS registry.\\n * @param node The node to update.\\n */\\n function clearRecords(bytes32 node) public virtual authorised(node) {\\n recordVersions[node]++;\\n emit VersionChanged(node, recordVersions[node]);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IVersionableResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x893049fffd6feee06d7acef1680f6e26505bedff62a9f7a17e921c0ba2f66307\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/AddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./IAddrResolver.sol\\\";\\nimport \\\"./IAddressResolver.sol\\\";\\n\\nabstract contract AddrResolver is\\n IAddrResolver,\\n IAddressResolver,\\n ResolverBase\\n{\\n uint256 private constant COIN_TYPE_ETH = 60;\\n\\n mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_addresses;\\n\\n /**\\n * Sets the address associated with an ENS node.\\n * May only be called by the owner of that node in the ENS registry.\\n * @param node The node to update.\\n * @param a The address to set.\\n */\\n function setAddr(\\n bytes32 node,\\n address a\\n ) external virtual authorised(node) {\\n setAddr(node, COIN_TYPE_ETH, addressToBytes(a));\\n }\\n\\n /**\\n * Returns the address associated with an ENS node.\\n * @param node The ENS node to query.\\n * @return The associated address.\\n */\\n function addr(\\n bytes32 node\\n ) public view virtual override returns (address payable) {\\n bytes memory a = addr(node, COIN_TYPE_ETH);\\n if (a.length == 0) {\\n return payable(0);\\n }\\n return bytesToAddress(a);\\n }\\n\\n function setAddr(\\n bytes32 node,\\n uint256 coinType,\\n bytes memory a\\n ) public virtual authorised(node) {\\n emit AddressChanged(node, coinType, a);\\n if (coinType == COIN_TYPE_ETH) {\\n emit AddrChanged(node, bytesToAddress(a));\\n }\\n versionable_addresses[recordVersions[node]][node][coinType] = a;\\n }\\n\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) public view virtual override returns (bytes memory) {\\n return versionable_addresses[recordVersions[node]][node][coinType];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IAddrResolver).interfaceId ||\\n interfaceID == type(IAddressResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n\\n function bytesToAddress(\\n bytes memory b\\n ) internal pure returns (address payable a) {\\n require(b.length == 20);\\n assembly {\\n a := div(mload(add(b, 32)), exp(256, 12))\\n }\\n }\\n\\n function addressToBytes(address a) internal pure returns (bytes memory b) {\\n b = new bytes(20);\\n assembly {\\n mstore(add(b, 32), mul(a, exp(256, 12)))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7f6ebb3144530a02db03379f33ade869c8408eceed36dfbd751aaff198735b55\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/**\\n * Interface for the legacy (ETH-only) addr function.\\n */\\ninterface IAddrResolver {\\n event AddrChanged(bytes32 indexed node, address a);\\n\\n /**\\n * Returns the address associated with an ENS node.\\n * @param node The ENS node to query.\\n * @return The associated address.\\n */\\n function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x2ad7f2fc60ebe0f93745fe70247f6a854f66af732483fda2a3c5e055614445e8\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/**\\n * Interface for the new (multicoin) addr function.\\n */\\ninterface IAddressResolver {\\n event AddressChanged(\\n bytes32 indexed node,\\n uint256 coinType,\\n bytes newAddress\\n );\\n\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x411447c1e90c51e09702815a85ec725ffbbe37cf96e8cc4d2a8bd4ad8a59d73e\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IVersionableResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IVersionableResolver {\\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\\n\\n function recordVersions(bytes32 node) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0xd0d09596f20c57bafb2ffa8521a8c57120e9af6c6b194f9c689d4da56f91a57c\",\"license\":\"MIT\"},\"contracts/root/Controllable.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract Controllable is Ownable {\\n mapping(address => bool) public controllers;\\n\\n event ControllerChanged(address indexed controller, bool enabled);\\n\\n modifier onlyController() {\\n require(\\n controllers[msg.sender],\\n \\\"Controllable: Caller is not a controller\\\"\\n );\\n _;\\n }\\n\\n function setController(address controller, bool enabled) public onlyOwner {\\n controllers[controller] = enabled;\\n emit ControllerChanged(controller, enabled);\\n }\\n}\\n\",\"keccak256\":\"0xb19b8c0fafe9ca2b4bf8aaafee486fa31437672e1e1977bdf84bfe03464969db\"},\"contracts/root/Root.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"./Controllable.sol\\\";\\n\\ncontract Root is Ownable, Controllable {\\n bytes32 private constant ROOT_NODE = bytes32(0);\\n\\n bytes4 private constant INTERFACE_META_ID =\\n bytes4(keccak256(\\\"supportsInterface(bytes4)\\\"));\\n\\n event TLDLocked(bytes32 indexed label);\\n\\n ENS public ens;\\n mapping(bytes32 => bool) public locked;\\n\\n constructor(ENS _ens) public {\\n ens = _ens;\\n }\\n\\n function setSubnodeOwner(\\n bytes32 label,\\n address owner\\n ) external onlyController {\\n require(!locked[label]);\\n ens.setSubnodeOwner(ROOT_NODE, label, owner);\\n }\\n\\n function setResolver(address resolver) external onlyOwner {\\n ens.setResolver(ROOT_NODE, resolver);\\n }\\n\\n function lock(bytes32 label) external onlyOwner {\\n emit TLDLocked(label);\\n locked[label] = true;\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) external pure returns (bool) {\\n return interfaceID == INTERFACE_META_ID;\\n }\\n}\\n\",\"keccak256\":\"0x469b281e1a9e1c3dad9c860a4ab3a7299a48355b0b0243713e0829193c39f50c\"},\"contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /**\\n * @dev Attempts to parse bytes32 from a hex string\\n * @param str The string to parse\\n * @param idx The offset to start parsing at\\n * @param lastIdx The (exclusive) last index in `str` to consider. Use `str.length` to scan the whole string.\\n */\\n function hexStringToBytes32(\\n bytes memory str,\\n uint256 idx,\\n uint256 lastIdx\\n ) internal pure returns (bytes32 r, bool valid) {\\n valid = true;\\n assembly {\\n // check that the index to read to is not past the end of the string\\n if gt(lastIdx, mload(str)) {\\n revert(0, 0)\\n }\\n\\n function getHex(c) -> ascii {\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0xff\\n }\\n\\n let ptr := add(str, 32)\\n for {\\n let i := idx\\n } lt(i, lastIdx) {\\n i := add(i, 2)\\n } {\\n let byte1 := getHex(byte(0, mload(add(ptr, i))))\\n let byte2 := getHex(byte(0, mload(add(ptr, add(i, 1)))))\\n // if either byte is invalid, set invalid and break loop\\n if or(eq(byte1, 0xff), eq(byte2, 0xff)) {\\n valid := false\\n break\\n }\\n let combined := or(shl(4, byte1), byte2)\\n r := or(shl(8, r), combined)\\n }\\n }\\n }\\n\\n /**\\n * @dev Attempts to parse an address from a hex string\\n * @param str The string to parse\\n * @param idx The offset to start parsing at\\n * @param lastIdx The (exclusive) last index in `str` to consider. Use `str.length` to scan the whole string.\\n */\\n function hexToAddress(\\n bytes memory str,\\n uint256 idx,\\n uint256 lastIdx\\n ) internal pure returns (address, bool) {\\n if (lastIdx - idx < 40) return (address(0x0), false);\\n (bytes32 r, bool valid) = hexStringToBytes32(str, idx, lastIdx);\\n return (address(uint160(uint256(r))), valid);\\n }\\n}\\n\",\"keccak256\":\"0xcae20ad72181f47dfe7fba7d88e8d902a01576b16e93362878e726989d6cfb4d\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6101006040523480156200001257600080fd5b5060405162002344380380620023448339810160408190526200003591620000c8565b6001600160a01b0385811660c05284811660e05283811660a052600080546001600160a01b03191691841691821790556040519081527f9176b7f47e4504df5e5516c99d90d82ac7cbd49cc77e7f22ba2ac2f2e3a3eba89060200160405180910390a16001600160a01b0316608052506200014892505050565b6001600160a01b0381168114620000c557600080fd5b50565b600080600080600060a08688031215620000e157600080fd5b8551620000ee81620000af565b60208701519095506200010181620000af565b60408701519094506200011481620000af565b60608701519093506200012781620000af565b60808701519092506200013a81620000af565b809150509295509295909350565b60805160a05160c05160e051612176620001ce6000396000818160fb01528181610cde0152610d950152600081816102320152610b6301526000818161020b01526108020152600081816101c301528181610397015281816104f8015281816106b301528181610ae301528181610bba01528181610d060152610dc401526121766000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c806329d56630116100815780636f9512211161005b5780636f951221146101e55780637dc0d1d014610206578063ab14ec591461022d57600080fd5b806329d566301461019857806330349ebe146101ab5780633f15457f146101be57600080fd5b806306963218116100b257806306963218146101355780631ecfc4111461014a57806325916d411461015d57600080fd5b806301ffc9a7146100ce57806304f3bcec146100f6575b600080fd5b6100e16100dc3660046119d8565b610254565b60405190151581526020015b60405180910390f35b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100ed565b610148610143366004611c1a565b6102ed565b005b610148610158366004611ca3565b6104df565b61018361016b366004611cc0565b60016020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016100ed565b6101486101a6366004611cd9565b610656565b60005461011d906001600160a01b031681565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b6101f86101f3366004611d3d565b61072a565b6040519081526020016100ed565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102e757507fffffffff0000000000000000000000000000000000000000000000000000000082167f2f43542800000000000000000000000000000000000000000000000000000000145b92915050565b60008060006102fc87876107f8565b91945092509050336001600160a01b0382161461035b576040517fe03f60240000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03821660248201526044015b60405180910390fd5b6040516305ef2c7f60e41b815260048101849052602481018390526001600160a01b0382811660448301528681166064830152600060848301527f00000000000000000000000000000000000000000000000000000000000000001690635ef2c7f09060a401600060405180830381600087803b1580156103db57600080fd5b505af11580156103ef573d6000803e3d6000fd5b505050506001600160a01b038416156104d6576001600160a01b03851661042957604051633c584f1360e21b815260040160405180910390fd5b604080516020810185905290810183905260009060600160408051808303601f190181529082905280516020909101207fd5fa2b00000000000000000000000000000000000000000000000000000000008252600482018190526001600160a01b03878116602484015290925087169063d5fa2b0090604401600060405180830381600087803b1580156104bc57600080fd5b505af11580156104d0573d6000803e3d6000fd5b50505050505b50505050505050565b6040516302571be360e01b8152600060048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015610547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056b9190611d72565b90506000816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d19190611d72565b9050336001600160a01b038216146105e857600080fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0385169081179091556040519081527f9176b7f47e4504df5e5516c99d90d82ac7cbd49cc77e7f22ba2ac2f2e3a3eba89060200160405180910390a1505050565b600080600061066585856107f8565b6040517f06ab592300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b03828116604483015293965091945092507f0000000000000000000000000000000000000000000000000000000000000000909116906306ab5923906064016020604051808303816000875af11580156106fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107229190611d8f565b505050505050565b600080546040517f4f89059e0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690634f89059e90610774908590600401611df8565b602060405180830381865afa158015610791573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b59190611e0b565b6107ed57816040517f396e24b80000000000000000000000000000000000000000000000000000000081526004016103529190611df8565b6102e7826000610a35565b60008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bdf95fef876040518263ffffffff1660e01b815260040161084c9190611e2d565b600060405180830381865afa158015610869573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108919190810190611eb2565b909250905060006108a28882610e58565b60ff1690506108b388600183610e7c565b945060006108e66108c5836001611f5f565b6001848c516108d49190611f72565b6108de9190611f72565b8b9190610ea0565b90506108f18161072a565b965060008787604051602001610911929190918252602082015260400190565b60408051808303601f190181529181528151602092830120600081815260019093529082205490925063ffffffff16850360030b121561097d576040517f2dd6a7af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260408120805463ffffffff191663ffffffff87161790556109a88b87610f22565b9097509050806109e4576040517f6260f6f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b866001600160a01b0316827f87db02a0e483e2818060eddcbb3488ce44e35aff49a70d92c2aa6c8046cf01e28d88604051610a20929190611f85565b60405180910390a35050505050509250925092565b600080610a428484610e58565b60ff16905080600003610a595750600090506102e7565b6000610a7985610a698487611f5f565b610a74906001611f5f565b610a35565b90506000610a93610a8b866001611f5f565b879085610e7c565b604080516020810185905290810182905290915060600160408051601f198184030181529082905280516020909101206302571be360e01b82526004820181905294506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906302571be390602401602060405180830381865afa158015610b2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4e9190611d72565b90506001600160a01b0381161580610b9757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316145b15610e255782610d6a576040516302571be360e01b8152600060048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d9190611d72565b6040517f8cb8ecec000000000000000000000000000000000000000000000000000000008152600481018590523060248201529091506001600160a01b03821690638cb8ecec90604401600060405180830381600087803b158015610c9157600080fd5b505af1158015610ca5573d6000803e3d6000fd5b50506040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018990526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000169250631896f70a9150604401600060405180830381600087803b158015610d4c57600080fd5b505af1158015610d60573d6000803e3d6000fd5b5050505050610e4e565b6040516305ef2c7f60e41b815260048101849052602481018390523060448201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166064830152600060848301527f00000000000000000000000000000000000000000000000000000000000000001690635ef2c7f09060a401600060405180830381600087803b158015610e0857600080fd5b505af1158015610e1c573d6000803e3d6000fd5b50505050610e4e565b6001600160a01b0381163014610e4e57604051633c584f1360e21b815260040160405180910390fd5b5050505092915050565b6000828281518110610e6c57610e6c611fad565b016020015160f81c905092915050565b8251600090610e8b8385611f5f565b1115610e9657600080fd5b5091016020012090565b8251606090610eaf8385611f5f565b1115610eba57600080fd5b60008267ffffffffffffffff811115610ed557610ed5611a1a565b6040519080825280601f01601f191660200182016040528015610eff576020820181803683370190505b50905060208082019086860101610f17828287611030565b509095945050505050565b600080610f42604051806040016040528060608152602001600081525090565b610f5a85516005610f539190611f5f565b8290611086565b5060408051808201909152600581527f045f656e730000000000000000000000000000000000000000000000000000006020820152610f9a9082906110fd565b50610fa581866110fd565b506000610fb28582611125565b90505b8051516020820151101561101f578151610fd890610fd283611186565b906111a7565b60000361101157600080610ff5878460a001518560c00151611300565b92509050811561100e5794506001935061102992505050565b50505b61101a81611373565b610fb5565b5060008092509250505b9250929050565b602081106110685781518352611047602084611f5f565b9250611054602083611f5f565b9150611061602082611f72565b9050611030565b905182516020929092036101000a6000190180199091169116179052565b6040805180820190915260608152600060208201526110a6602083611fc3565b156110ce576110b6602083611fc3565b6110c1906020611f72565b6110cb9083611f5f565b91505b6020808401839052604051808552600081529081840101818110156110f257600080fd5b604052509192915050565b60408051808201909152606081526000602082015261111e8383845161145b565b9392505050565b6111736040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c081018290526102e781611373565b602081015181516060916102e79161119e9082611531565b84519190610ea0565b60006111b38383611593565b156111c0575060006102e7565b60008060008060006111d38860006115b1565b905060006111e28860006115b1565b90505b8082111561120e578593506111fa898761160e565b95508161120681611fe5565b9250506111e5565b8181111561123757849250611223888661160e565b94508061122f81611fe5565b91505061120e565b600082118015611250575061124e89878a88611632565b155b1561128557859350611262898761160e565b9550849250611271888661160e565b945061127e600183611f72565b9150611237565b8560000361129d5760001996505050505050506102e7565b846000036112b457600196505050505050506102e7565b6112f36112c2856001611f5f565b6112cc8b87610e58565b60ff168a6112db876001611f5f565b6112e58d89610e58565b8e949392919060ff16611667565b9998505050505050505050565b6000805b828410156113645760006113188686610e58565b60ff169050611328600186611f5f565b94506000806113388888856117e5565b9250905081156113505793506001925061136b915050565b61135a8388611f5f565b9650505050611304565b5060009050805b935093915050565b60c0810151602082018190528151511161138a5750565b600061139e82600001518360200151611531565b82602001516113ad9190611f5f565b82519091506113bc9082611839565b61ffff1660408301526113d0600282611f5f565b82519091506113df9082611839565b61ffff1660608301526113f3600282611f5f565b82519091506114029082611861565b63ffffffff166080830152611418600482611f5f565b825190915060009061142a9083611839565b61ffff16905061143b600283611f5f565b60a08401819052915061144e8183611f5f565b60c0909301929092525050565b604080518082019091526060815260006020820152825182111561147e57600080fd5b835151600061148d8483611f5f565b905085602001518111156114af576114af866114aa836002611ffc565b61188b565b8551805183820160200191600091808511156114c9578482525b505050602086015b6020861061150957805182526114e8602083611f5f565b91506114f5602082611f5f565b9050611502602087611f72565b95506114d1565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b6000815b8351811061154557611545612013565b60006115518583610e58565b60ff169050611561816001611f5f565b61156b9083611f5f565b91508060000361157b5750611581565b50611535565b61158b8382611f72565b949350505050565b60008151835114801561111e575061111e83600084600087516118a8565b6000805b835183106115c5576115c5612013565b60006115d18585610e58565b60ff1690506115e1816001611f5f565b6115eb9085611f5f565b9350806000036115fb575061111e565b611606600183611f5f565b9150506115b5565b600061161a8383610e58565b60ff16611628836001611f5f565b61111e9190611f5f565b600061164b83838486516116469190611f72565b610e7c565b61165d86868789516116469190611f72565b1495945050505050565b85516000906116768688611f5f565b11156116aa576116868587611f5f565b8751604051638a3c1cfb60e01b815260048101929092526024820152604401610352565b83516116b68385611f5f565b11156116ea576116c68284611f5f565b8451604051638a3c1cfb60e01b815260048101929092526024820152604401610352565b84808310156116f65750815b60208789018101908587010160005b838110156117ca578251825180821461179a57600060206117268589611f72565b106117345750600019611770565b600187611742866020611f5f565b61174c9190611f72565b611757906008611ffc565b61176290600261210d565b61176c9190611f72565b1990505b6000611780838316858416612119565b905080156117975797506117db9650505050505050565b50505b6117a5602086611f5f565b94506117b2602085611f5f565b935050506020816117c39190611f5f565b9050611705565b506117d58589612119565b93505050505b9695505050505050565b6000806117f28585611861565b63ffffffff1663613d30781461180d5750600090508061136b565b61182d61181b856004611f5f565b6118258587611f5f565b8791906118cb565b91509150935093915050565b8151600090611849836002611f5f565b111561185457600080fd5b50016002015161ffff1690565b8151600090611871836004611f5f565b111561187c57600080fd5b50016004015163ffffffff1690565b81516118978383611086565b506118a283826110fd565b50505050565b60006118b5848484610e7c565b6118c0878785610e7c565b149695505050505050565b60008060286118da8585611f72565b10156118eb5750600090508061136b565b6000806118f9878787611907565b909890975095505050505050565b825160009060019083111561191b57600080fd5b61196c565b6000603a8210602f831116156119385750602f190190565b6047821060408311161561194e57506036190190565b6067821060608311161561196457506056190190565b5060ff919050565b60208501845b848110156119ce576119898183015160001a611920565b61199b6001830184015160001a611920565b60ff811460ff831417156119b4576000945050506119ce565b60049190911b1760089490941b9390931792600201611972565b5050935093915050565b6000602082840312156119ea57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461111e57600080fd5b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611a5357611a53611a1a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611a8257611a82611a1a565b604052919050565b600067ffffffffffffffff821115611aa457611aa4611a1a565b50601f01601f191660200190565b600082601f830112611ac357600080fd5b8135611ad6611ad182611a8a565b611a59565b818152846020838601011115611aeb57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112611b1957600080fd5b8135602067ffffffffffffffff80831115611b3657611b36611a1a565b8260051b611b45838201611a59565b9384528581018301938381019088861115611b5f57600080fd5b84880192505b85831015611bf657823584811115611b7d5760008081fd5b88016040818b03601f1901811315611b955760008081fd5b611b9d611a30565b8783013587811115611baf5760008081fd5b611bbd8d8a83870101611ab2565b825250908201359086821115611bd35760008081fd5b611be18c8984860101611ab2565b81890152845250509184019190840190611b65565b98975050505050505050565b6001600160a01b0381168114611c1757600080fd5b50565b60008060008060808587031215611c3057600080fd5b843567ffffffffffffffff80821115611c4857600080fd5b611c5488838901611ab2565b95506020870135915080821115611c6a57600080fd5b50611c7787828801611b08565b9350506040850135611c8881611c02565b91506060850135611c9881611c02565b939692955090935050565b600060208284031215611cb557600080fd5b813561111e81611c02565b600060208284031215611cd257600080fd5b5035919050565b60008060408385031215611cec57600080fd5b823567ffffffffffffffff80821115611d0457600080fd5b611d1086838701611ab2565b93506020850135915080821115611d2657600080fd5b50611d3385828601611b08565b9150509250929050565b600060208284031215611d4f57600080fd5b813567ffffffffffffffff811115611d6657600080fd5b61158b84828501611ab2565b600060208284031215611d8457600080fd5b815161111e81611c02565b600060208284031215611da157600080fd5b5051919050565b60005b83811015611dc3578181015183820152602001611dab565b50506000910152565b60008151808452611de4816020860160208601611da8565b601f01601f19169290920160200192915050565b60208152600061111e6020830184611dcc565b600060208284031215611e1d57600080fd5b8151801515811461111e57600080fd5b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611ea457888303603f1901855281518051878552611e7888860182611dcc565b91890151858303868b0152919050611e908183611dcc565b968901969450505090860190600101611e54565b509098975050505050505050565b60008060408385031215611ec557600080fd5b825167ffffffffffffffff811115611edc57600080fd5b8301601f81018513611eed57600080fd5b8051611efb611ad182611a8a565b818152866020838501011115611f1057600080fd5b611f21826020830160208601611da8565b809450505050602083015163ffffffff81168114611f3e57600080fd5b809150509250929050565b634e487b7160e01b600052601160045260246000fd5b808201808211156102e7576102e7611f49565b818103818111156102e7576102e7611f49565b604081526000611f986040830185611dcc565b905063ffffffff831660208301529392505050565b634e487b7160e01b600052603260045260246000fd5b600082611fe057634e487b7160e01b600052601260045260246000fd5b500690565b600081611ff457611ff4611f49565b506000190190565b80820281158282048414176102e7576102e7611f49565b634e487b7160e01b600052600160045260246000fd5b600181815b8085111561206457816000190482111561204a5761204a611f49565b8085161561205757918102915b93841c939080029061202e565b509250929050565b60008261207b575060016102e7565b81612088575060006102e7565b816001811461209e57600281146120a8576120c4565b60019150506102e7565b60ff8411156120b9576120b9611f49565b50506001821b6102e7565b5060208310610133831016604e8410600b84101617156120e7575081810a6102e7565b6120f18383612029565b806000190482111561210557612105611f49565b029392505050565b600061111e838361206c565b818103600083128015838313168383128216171561213957612139611f49565b509291505056fea2646970667358221220d68296b3ce766db7fdbff297a4001c8844f685315060863afb54ec523b7470f664736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100c95760003560e01c806329d56630116100815780636f9512211161005b5780636f951221146101e55780637dc0d1d014610206578063ab14ec591461022d57600080fd5b806329d566301461019857806330349ebe146101ab5780633f15457f146101be57600080fd5b806306963218116100b257806306963218146101355780631ecfc4111461014a57806325916d411461015d57600080fd5b806301ffc9a7146100ce57806304f3bcec146100f6575b600080fd5b6100e16100dc3660046119d8565b610254565b60405190151581526020015b60405180910390f35b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100ed565b610148610143366004611c1a565b6102ed565b005b610148610158366004611ca3565b6104df565b61018361016b366004611cc0565b60016020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016100ed565b6101486101a6366004611cd9565b610656565b60005461011d906001600160a01b031681565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b6101f86101f3366004611d3d565b61072a565b6040519081526020016100ed565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b61011d7f000000000000000000000000000000000000000000000000000000000000000081565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102e757507fffffffff0000000000000000000000000000000000000000000000000000000082167f2f43542800000000000000000000000000000000000000000000000000000000145b92915050565b60008060006102fc87876107f8565b91945092509050336001600160a01b0382161461035b576040517fe03f60240000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03821660248201526044015b60405180910390fd5b6040516305ef2c7f60e41b815260048101849052602481018390526001600160a01b0382811660448301528681166064830152600060848301527f00000000000000000000000000000000000000000000000000000000000000001690635ef2c7f09060a401600060405180830381600087803b1580156103db57600080fd5b505af11580156103ef573d6000803e3d6000fd5b505050506001600160a01b038416156104d6576001600160a01b03851661042957604051633c584f1360e21b815260040160405180910390fd5b604080516020810185905290810183905260009060600160408051808303601f190181529082905280516020909101207fd5fa2b00000000000000000000000000000000000000000000000000000000008252600482018190526001600160a01b03878116602484015290925087169063d5fa2b0090604401600060405180830381600087803b1580156104bc57600080fd5b505af11580156104d0573d6000803e3d6000fd5b50505050505b50505050505050565b6040516302571be360e01b8152600060048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015610547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056b9190611d72565b90506000816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d19190611d72565b9050336001600160a01b038216146105e857600080fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0385169081179091556040519081527f9176b7f47e4504df5e5516c99d90d82ac7cbd49cc77e7f22ba2ac2f2e3a3eba89060200160405180910390a1505050565b600080600061066585856107f8565b6040517f06ab592300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b03828116604483015293965091945092507f0000000000000000000000000000000000000000000000000000000000000000909116906306ab5923906064016020604051808303816000875af11580156106fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107229190611d8f565b505050505050565b600080546040517f4f89059e0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690634f89059e90610774908590600401611df8565b602060405180830381865afa158015610791573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b59190611e0b565b6107ed57816040517f396e24b80000000000000000000000000000000000000000000000000000000081526004016103529190611df8565b6102e7826000610a35565b60008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bdf95fef876040518263ffffffff1660e01b815260040161084c9190611e2d565b600060405180830381865afa158015610869573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108919190810190611eb2565b909250905060006108a28882610e58565b60ff1690506108b388600183610e7c565b945060006108e66108c5836001611f5f565b6001848c516108d49190611f72565b6108de9190611f72565b8b9190610ea0565b90506108f18161072a565b965060008787604051602001610911929190918252602082015260400190565b60408051808303601f190181529181528151602092830120600081815260019093529082205490925063ffffffff16850360030b121561097d576040517f2dd6a7af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260408120805463ffffffff191663ffffffff87161790556109a88b87610f22565b9097509050806109e4576040517f6260f6f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b866001600160a01b0316827f87db02a0e483e2818060eddcbb3488ce44e35aff49a70d92c2aa6c8046cf01e28d88604051610a20929190611f85565b60405180910390a35050505050509250925092565b600080610a428484610e58565b60ff16905080600003610a595750600090506102e7565b6000610a7985610a698487611f5f565b610a74906001611f5f565b610a35565b90506000610a93610a8b866001611f5f565b879085610e7c565b604080516020810185905290810182905290915060600160408051601f198184030181529082905280516020909101206302571be360e01b82526004820181905294506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906302571be390602401602060405180830381865afa158015610b2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4e9190611d72565b90506001600160a01b0381161580610b9757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316145b15610e255782610d6a576040516302571be360e01b8152600060048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d9190611d72565b6040517f8cb8ecec000000000000000000000000000000000000000000000000000000008152600481018590523060248201529091506001600160a01b03821690638cb8ecec90604401600060405180830381600087803b158015610c9157600080fd5b505af1158015610ca5573d6000803e3d6000fd5b50506040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018990526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000169250631896f70a9150604401600060405180830381600087803b158015610d4c57600080fd5b505af1158015610d60573d6000803e3d6000fd5b5050505050610e4e565b6040516305ef2c7f60e41b815260048101849052602481018390523060448201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166064830152600060848301527f00000000000000000000000000000000000000000000000000000000000000001690635ef2c7f09060a401600060405180830381600087803b158015610e0857600080fd5b505af1158015610e1c573d6000803e3d6000fd5b50505050610e4e565b6001600160a01b0381163014610e4e57604051633c584f1360e21b815260040160405180910390fd5b5050505092915050565b6000828281518110610e6c57610e6c611fad565b016020015160f81c905092915050565b8251600090610e8b8385611f5f565b1115610e9657600080fd5b5091016020012090565b8251606090610eaf8385611f5f565b1115610eba57600080fd5b60008267ffffffffffffffff811115610ed557610ed5611a1a565b6040519080825280601f01601f191660200182016040528015610eff576020820181803683370190505b50905060208082019086860101610f17828287611030565b509095945050505050565b600080610f42604051806040016040528060608152602001600081525090565b610f5a85516005610f539190611f5f565b8290611086565b5060408051808201909152600581527f045f656e730000000000000000000000000000000000000000000000000000006020820152610f9a9082906110fd565b50610fa581866110fd565b506000610fb28582611125565b90505b8051516020820151101561101f578151610fd890610fd283611186565b906111a7565b60000361101157600080610ff5878460a001518560c00151611300565b92509050811561100e5794506001935061102992505050565b50505b61101a81611373565b610fb5565b5060008092509250505b9250929050565b602081106110685781518352611047602084611f5f565b9250611054602083611f5f565b9150611061602082611f72565b9050611030565b905182516020929092036101000a6000190180199091169116179052565b6040805180820190915260608152600060208201526110a6602083611fc3565b156110ce576110b6602083611fc3565b6110c1906020611f72565b6110cb9083611f5f565b91505b6020808401839052604051808552600081529081840101818110156110f257600080fd5b604052509192915050565b60408051808201909152606081526000602082015261111e8383845161145b565b9392505050565b6111736040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c081018290526102e781611373565b602081015181516060916102e79161119e9082611531565b84519190610ea0565b60006111b38383611593565b156111c0575060006102e7565b60008060008060006111d38860006115b1565b905060006111e28860006115b1565b90505b8082111561120e578593506111fa898761160e565b95508161120681611fe5565b9250506111e5565b8181111561123757849250611223888661160e565b94508061122f81611fe5565b91505061120e565b600082118015611250575061124e89878a88611632565b155b1561128557859350611262898761160e565b9550849250611271888661160e565b945061127e600183611f72565b9150611237565b8560000361129d5760001996505050505050506102e7565b846000036112b457600196505050505050506102e7565b6112f36112c2856001611f5f565b6112cc8b87610e58565b60ff168a6112db876001611f5f565b6112e58d89610e58565b8e949392919060ff16611667565b9998505050505050505050565b6000805b828410156113645760006113188686610e58565b60ff169050611328600186611f5f565b94506000806113388888856117e5565b9250905081156113505793506001925061136b915050565b61135a8388611f5f565b9650505050611304565b5060009050805b935093915050565b60c0810151602082018190528151511161138a5750565b600061139e82600001518360200151611531565b82602001516113ad9190611f5f565b82519091506113bc9082611839565b61ffff1660408301526113d0600282611f5f565b82519091506113df9082611839565b61ffff1660608301526113f3600282611f5f565b82519091506114029082611861565b63ffffffff166080830152611418600482611f5f565b825190915060009061142a9083611839565b61ffff16905061143b600283611f5f565b60a08401819052915061144e8183611f5f565b60c0909301929092525050565b604080518082019091526060815260006020820152825182111561147e57600080fd5b835151600061148d8483611f5f565b905085602001518111156114af576114af866114aa836002611ffc565b61188b565b8551805183820160200191600091808511156114c9578482525b505050602086015b6020861061150957805182526114e8602083611f5f565b91506114f5602082611f5f565b9050611502602087611f72565b95506114d1565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b6000815b8351811061154557611545612013565b60006115518583610e58565b60ff169050611561816001611f5f565b61156b9083611f5f565b91508060000361157b5750611581565b50611535565b61158b8382611f72565b949350505050565b60008151835114801561111e575061111e83600084600087516118a8565b6000805b835183106115c5576115c5612013565b60006115d18585610e58565b60ff1690506115e1816001611f5f565b6115eb9085611f5f565b9350806000036115fb575061111e565b611606600183611f5f565b9150506115b5565b600061161a8383610e58565b60ff16611628836001611f5f565b61111e9190611f5f565b600061164b83838486516116469190611f72565b610e7c565b61165d86868789516116469190611f72565b1495945050505050565b85516000906116768688611f5f565b11156116aa576116868587611f5f565b8751604051638a3c1cfb60e01b815260048101929092526024820152604401610352565b83516116b68385611f5f565b11156116ea576116c68284611f5f565b8451604051638a3c1cfb60e01b815260048101929092526024820152604401610352565b84808310156116f65750815b60208789018101908587010160005b838110156117ca578251825180821461179a57600060206117268589611f72565b106117345750600019611770565b600187611742866020611f5f565b61174c9190611f72565b611757906008611ffc565b61176290600261210d565b61176c9190611f72565b1990505b6000611780838316858416612119565b905080156117975797506117db9650505050505050565b50505b6117a5602086611f5f565b94506117b2602085611f5f565b935050506020816117c39190611f5f565b9050611705565b506117d58589612119565b93505050505b9695505050505050565b6000806117f28585611861565b63ffffffff1663613d30781461180d5750600090508061136b565b61182d61181b856004611f5f565b6118258587611f5f565b8791906118cb565b91509150935093915050565b8151600090611849836002611f5f565b111561185457600080fd5b50016002015161ffff1690565b8151600090611871836004611f5f565b111561187c57600080fd5b50016004015163ffffffff1690565b81516118978383611086565b506118a283826110fd565b50505050565b60006118b5848484610e7c565b6118c0878785610e7c565b149695505050505050565b60008060286118da8585611f72565b10156118eb5750600090508061136b565b6000806118f9878787611907565b909890975095505050505050565b825160009060019083111561191b57600080fd5b61196c565b6000603a8210602f831116156119385750602f190190565b6047821060408311161561194e57506036190190565b6067821060608311161561196457506056190190565b5060ff919050565b60208501845b848110156119ce576119898183015160001a611920565b61199b6001830184015160001a611920565b60ff811460ff831417156119b4576000945050506119ce565b60049190911b1760089490941b9390931792600201611972565b5050935093915050565b6000602082840312156119ea57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461111e57600080fd5b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611a5357611a53611a1a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611a8257611a82611a1a565b604052919050565b600067ffffffffffffffff821115611aa457611aa4611a1a565b50601f01601f191660200190565b600082601f830112611ac357600080fd5b8135611ad6611ad182611a8a565b611a59565b818152846020838601011115611aeb57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112611b1957600080fd5b8135602067ffffffffffffffff80831115611b3657611b36611a1a565b8260051b611b45838201611a59565b9384528581018301938381019088861115611b5f57600080fd5b84880192505b85831015611bf657823584811115611b7d5760008081fd5b88016040818b03601f1901811315611b955760008081fd5b611b9d611a30565b8783013587811115611baf5760008081fd5b611bbd8d8a83870101611ab2565b825250908201359086821115611bd35760008081fd5b611be18c8984860101611ab2565b81890152845250509184019190840190611b65565b98975050505050505050565b6001600160a01b0381168114611c1757600080fd5b50565b60008060008060808587031215611c3057600080fd5b843567ffffffffffffffff80821115611c4857600080fd5b611c5488838901611ab2565b95506020870135915080821115611c6a57600080fd5b50611c7787828801611b08565b9350506040850135611c8881611c02565b91506060850135611c9881611c02565b939692955090935050565b600060208284031215611cb557600080fd5b813561111e81611c02565b600060208284031215611cd257600080fd5b5035919050565b60008060408385031215611cec57600080fd5b823567ffffffffffffffff80821115611d0457600080fd5b611d1086838701611ab2565b93506020850135915080821115611d2657600080fd5b50611d3385828601611b08565b9150509250929050565b600060208284031215611d4f57600080fd5b813567ffffffffffffffff811115611d6657600080fd5b61158b84828501611ab2565b600060208284031215611d8457600080fd5b815161111e81611c02565b600060208284031215611da157600080fd5b5051919050565b60005b83811015611dc3578181015183820152602001611dab565b50506000910152565b60008151808452611de4816020860160208601611da8565b601f01601f19169290920160200192915050565b60208152600061111e6020830184611dcc565b600060208284031215611e1d57600080fd5b8151801515811461111e57600080fd5b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611ea457888303603f1901855281518051878552611e7888860182611dcc565b91890151858303868b0152919050611e908183611dcc565b968901969450505090860190600101611e54565b509098975050505050505050565b60008060408385031215611ec557600080fd5b825167ffffffffffffffff811115611edc57600080fd5b8301601f81018513611eed57600080fd5b8051611efb611ad182611a8a565b818152866020838501011115611f1057600080fd5b611f21826020830160208601611da8565b809450505050602083015163ffffffff81168114611f3e57600080fd5b809150509250929050565b634e487b7160e01b600052601160045260246000fd5b808201808211156102e7576102e7611f49565b818103818111156102e7576102e7611f49565b604081526000611f986040830185611dcc565b905063ffffffff831660208301529392505050565b634e487b7160e01b600052603260045260246000fd5b600082611fe057634e487b7160e01b600052601260045260246000fd5b500690565b600081611ff457611ff4611f49565b506000190190565b80820281158282048414176102e7576102e7611f49565b634e487b7160e01b600052600160045260246000fd5b600181815b8085111561206457816000190482111561204a5761204a611f49565b8085161561205757918102915b93841c939080029061202e565b509250929050565b60008261207b575060016102e7565b81612088575060006102e7565b816001811461209e57600281146120a8576120c4565b60019150506102e7565b60ff8411156120b9576120b9611f49565b50506001821b6102e7565b5060208310610133831016604e8410600b84101617156120e7575081810a6102e7565b6120f18383612029565b806000190482111561210557612105611f49565b029392505050565b600061111e838361206c565b818103600083128015838313168383128216171561213957612139611f49565b509291505056fea2646970667358221220d68296b3ce766db7fdbff297a4001c8844f685315060863afb54ec523b7470f664736f6c63430008110033", + "devdoc": { + "details": "An ENS registrar that allows the owner of a DNS name to claim the corresponding name in ENS.", + "kind": "dev", + "methods": { + "proveAndClaim(bytes,(bytes,bytes)[])": { + "details": "Submits proofs to the DNSSEC oracle, then claims a name using those proofs.", + "params": { + "input": "A chain of signed DNS RRSETs ending with a text record.", + "name": "The name to claim, in DNS wire format." + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 4216, + "contract": "contracts/dnsregistrar/DNSRegistrar.sol:DNSRegistrar", + "label": "suffixes", + "offset": 0, + "slot": "0", + "type": "t_contract(PublicSuffixList)5436" + }, + { + "astId": 4224, + "contract": "contracts/dnsregistrar/DNSRegistrar.sol:DNSRegistrar", + "label": "inceptions", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint32)" + } + ], + "types": { + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(PublicSuffixList)5436": { + "encoding": "inplace", + "label": "contract PublicSuffixList", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint32)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint32)", + "numberOfBytes": "32", + "value": "t_uint32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + } + } + } +} \ No newline at end of file diff --git a/deployments/sepolia/DNSSECImpl.json b/deployments/sepolia/DNSSECImpl.json new file mode 100644 index 00000000..3bfab13a --- /dev/null +++ b/deployments/sepolia/DNSSECImpl.json @@ -0,0 +1,530 @@ +{ + "address": "0x7b3ada1c8f012bae747cf99d6cbbf70d040b84cf", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "_anchors", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "class", + "type": "uint16" + } + ], + "name": "InvalidClass", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "labelsExpected", + "type": "uint256" + } + ], + "name": "InvalidLabelCount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "proofType", + "type": "uint16" + } + ], + "name": "InvalidProofType", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRRSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "rrsetName", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signerName", + "type": "bytes" + } + ], + "name": "InvalidSignerName", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signerName", + "type": "bytes" + } + ], + "name": "NoMatchingProof", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signerName", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "proofName", + "type": "bytes" + } + ], + "name": "ProofNameMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "expiration", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "now", + "type": "uint32" + } + ], + "name": "SignatureExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "inception", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "now", + "type": "uint32" + } + ], + "name": "SignatureNotValidYet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "rrsetType", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "sigType", + "type": "uint16" + } + ], + "name": "SignatureTypeMismatch", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "id", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "AlgorithmUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "id", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "DigestUpdated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "algorithms", + "outputs": [ + { + "internalType": "contract Algorithm", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "anchors", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "digests", + "outputs": [ + { + "internalType": "contract Digest", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + }, + { + "internalType": "contract Algorithm", + "name": "algo", + "type": "address" + } + ], + "name": "setAlgorithm", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + }, + { + "internalType": "contract Digest", + "name": "digest", + "type": "address" + } + ], + "name": "setDigest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "setOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "rrset", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "sig", + "type": "bytes" + } + ], + "internalType": "struct DNSSEC.RRSetWithSignature[]", + "name": "input", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "now", + "type": "uint256" + } + ], + "name": "verifyRRSet", + "outputs": [ + { + "internalType": "bytes", + "name": "rrs", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "inception", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "rrset", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "sig", + "type": "bytes" + } + ], + "internalType": "struct DNSSEC.RRSetWithSignature[]", + "name": "input", + "type": "tuple[]" + } + ], + "name": "verifyRRSet", + "outputs": [ + { + "internalType": "bytes", + "name": "rrs", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "inception", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xbd9e31d12f910b16bcf44cca8cc7df588845e42c1b7224e048b44f8bb4e43930", + "receipt": { + "to": null, + "from": "0x4fe4e666be5752f1fdd210f4ab5de2cc26e3e0e8", + "contractAddress": "0x7b3ada1c8f012bae747cf99d6cbbf70d040b84cf", + "transactionIndex": "0x95", + "gasUsed": "0x1bf79b", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc0307b65afb8138fd6e4dcc8f0593ba65cb1285020322e92139e7f5c170e5eac", + "transactionHash": "0x6ddfcb3aab9f6d406c1da5afb5717f2c6a330542efc1632ceb50e33cfa13dc97", + "logs": [], + "blockNumber": "0x3e6f3e", + "cumulativeGasUsed": "0xa4a607", + "status": "0x1" + }, + "args": [ + "0x00002b000100000e1000244a5c080249aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb500002b000100000e1000244f660802e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d00002b000100000e10000404fefdfd" + ], + "numDeployments": 1, + "solcInputHash": "e04502f562d98d0455f6c1c453418cdd", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_anchors\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"class\",\"type\":\"uint16\"}],\"name\":\"InvalidClass\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"labelsExpected\",\"type\":\"uint256\"}],\"name\":\"InvalidLabelCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"proofType\",\"type\":\"uint16\"}],\"name\":\"InvalidProofType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRRSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"rrsetName\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signerName\",\"type\":\"bytes\"}],\"name\":\"InvalidSignerName\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signerName\",\"type\":\"bytes\"}],\"name\":\"NoMatchingProof\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signerName\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofName\",\"type\":\"bytes\"}],\"name\":\"ProofNameMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expiration\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"now\",\"type\":\"uint32\"}],\"name\":\"SignatureExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"inception\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"now\",\"type\":\"uint32\"}],\"name\":\"SignatureNotValidYet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"rrsetType\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"sigType\",\"type\":\"uint16\"}],\"name\":\"SignatureTypeMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"AlgorithmUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"DigestUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"algorithms\",\"outputs\":[{\"internalType\":\"contract Algorithm\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"anchors\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"digests\",\"outputs\":[{\"internalType\":\"contract Digest\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"internalType\":\"contract Algorithm\",\"name\":\"algo\",\"type\":\"address\"}],\"name\":\"setAlgorithm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"internalType\":\"contract Digest\",\"name\":\"digest\",\"type\":\"address\"}],\"name\":\"setDigest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature[]\",\"name\":\"input\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"now\",\"type\":\"uint256\"}],\"name\":\"verifyRRSet\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"rrs\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"inception\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature[]\",\"name\":\"input\",\"type\":\"tuple[]\"}],\"name\":\"verifyRRSet\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"rrs\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"inception\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Constructor.\",\"params\":{\"_anchors\":\"The binary format RR entries for the root DS records.\"}},\"setAlgorithm(uint8,address)\":{\"details\":\"Sets the contract address for a signature verification algorithm. Callable only by the owner.\",\"params\":{\"algo\":\"The address of the algorithm contract.\",\"id\":\"The algorithm ID\"}},\"setDigest(uint8,address)\":{\"details\":\"Sets the contract address for a digest verification algorithm. Callable only by the owner.\",\"params\":{\"digest\":\"The address of the digest contract.\",\"id\":\"The digest ID\"}},\"verifyRRSet((bytes,bytes)[])\":{\"details\":\"Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain. Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.\",\"params\":{\"input\":\"A list of signed RRSets.\"},\"returns\":{\"inception\":\"The inception time of the signed record set.\",\"rrs\":\"The RRData from the last RRSet in the chain.\"}},\"verifyRRSet((bytes,bytes)[],uint256)\":{\"details\":\"Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain. Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.\",\"params\":{\"input\":\"A list of signed RRSets.\",\"now\":\"The Unix timestamp to validate the records at.\"},\"returns\":{\"inception\":\"The inception time of the signed record set.\",\"rrs\":\"The RRData from the last RRSet in the chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/DNSSECImpl.sol\":\"DNSSECImpl\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"@ensdomains/buffer/contracts/Buffer.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-2-Clause\\npragma solidity ^0.8.4;\\n\\n/**\\n* @dev A library for working with mutable byte buffers in Solidity.\\n*\\n* Byte buffers are mutable and expandable, and provide a variety of primitives\\n* for appending to them. At any time you can fetch a bytes object containing the\\n* current contents of the buffer. The bytes object should not be stored between\\n* operations, as it may change due to resizing of the buffer.\\n*/\\nlibrary Buffer {\\n /**\\n * @dev Represents a mutable buffer. Buffers have a current value (buf) and\\n * a capacity. The capacity may be longer than the current value, in\\n * which case it can be extended without the need to allocate more memory.\\n */\\n struct buffer {\\n bytes buf;\\n uint capacity;\\n }\\n\\n /**\\n * @dev Initializes a buffer with an initial capacity.\\n * @param buf The buffer to initialize.\\n * @param capacity The number of bytes of space to allocate the buffer.\\n * @return The buffer, for chaining.\\n */\\n function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {\\n if (capacity % 32 != 0) {\\n capacity += 32 - (capacity % 32);\\n }\\n // Allocate space for the buffer data\\n buf.capacity = capacity;\\n assembly {\\n let ptr := mload(0x40)\\n mstore(buf, ptr)\\n mstore(ptr, 0)\\n let fpm := add(32, add(ptr, capacity))\\n if lt(fpm, ptr) {\\n revert(0, 0)\\n }\\n mstore(0x40, fpm)\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Initializes a new buffer from an existing bytes object.\\n * Changes to the buffer may mutate the original value.\\n * @param b The bytes object to initialize the buffer with.\\n * @return A new buffer.\\n */\\n function fromBytes(bytes memory b) internal pure returns(buffer memory) {\\n buffer memory buf;\\n buf.buf = b;\\n buf.capacity = b.length;\\n return buf;\\n }\\n\\n function resize(buffer memory buf, uint capacity) private pure {\\n bytes memory oldbuf = buf.buf;\\n init(buf, capacity);\\n append(buf, oldbuf);\\n }\\n\\n /**\\n * @dev Sets buffer length to 0.\\n * @param buf The buffer to truncate.\\n * @return The original buffer, for chaining..\\n */\\n function truncate(buffer memory buf) internal pure returns (buffer memory) {\\n assembly {\\n let bufptr := mload(buf)\\n mstore(bufptr, 0)\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to copy.\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) {\\n require(len <= data.length);\\n\\n uint off = buf.buf.length;\\n uint newCapacity = off + len;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n uint dest;\\n uint src;\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Length of existing buffer data\\n let buflen := mload(bufptr)\\n // Start address = buffer address + offset + sizeof(buffer length)\\n dest := add(add(bufptr, 32), off)\\n // Update buffer length if we're extending it\\n if gt(newCapacity, buflen) {\\n mstore(bufptr, newCapacity)\\n }\\n src := add(data, 32)\\n }\\n\\n // Copy word-length chunks while possible\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n // Copy remaining bytes\\n unchecked {\\n uint mask = (256 ** (32 - len)) - 1;\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n\\n return buf;\\n }\\n\\n /**\\n * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\\n return append(buf, data, data.length);\\n }\\n\\n /**\\n * @dev Appends a byte to the buffer. Resizes if doing so would exceed the\\n * capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint offPlusOne = off + 1;\\n if (off >= buf.capacity) {\\n resize(buf, offPlusOne * 2);\\n }\\n\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + off\\n let dest := add(add(bufptr, off), 32)\\n mstore8(dest, data)\\n // Update buffer length if we extended it\\n if gt(offPlusOne, mload(bufptr)) {\\n mstore(bufptr, offPlusOne)\\n }\\n }\\n\\n return buf;\\n }\\n\\n /**\\n * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would\\n * exceed the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to write (left-aligned).\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint newCapacity = len + off;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n unchecked {\\n uint mask = (256 ** len) - 1;\\n // Right-align data\\n data = data >> (8 * (32 - len));\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + newCapacity\\n let dest := add(bufptr, newCapacity)\\n mstore(dest, or(and(mload(dest), not(mask)), data))\\n // Update buffer length if we extended it\\n if gt(newCapacity, mload(bufptr)) {\\n mstore(bufptr, newCapacity)\\n }\\n }\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chhaining.\\n */\\n function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {\\n return append(buf, bytes32(data), 20);\\n }\\n\\n /**\\n * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {\\n return append(buf, data, 32);\\n }\\n\\n /**\\n * @dev Appends a byte to the end of the buffer. Resizes if doing so would\\n * exceed the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to write (right-aligned).\\n * @return The original buffer.\\n */\\n function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint newCapacity = len + off;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n uint mask = (256 ** len) - 1;\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + newCapacity\\n let dest := add(bufptr, newCapacity)\\n mstore(dest, or(and(mload(dest), not(mask)), data))\\n // Update buffer length if we extended it\\n if gt(newCapacity, mload(bufptr)) {\\n mstore(bufptr, newCapacity)\\n }\\n }\\n return buf;\\n }\\n}\\n\",\"keccak256\":\"0xd6dd3b0b327288f8e1b711a609f4040fea602e2ad4bba9febdf2f33b4e56eb0c\",\"license\":\"BSD-2-Clause\"},\"contracts/dnssec-oracle/BytesUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary BytesUtils {\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /*\\n * @dev Returns the keccak-256 hash of a byte range.\\n * @param self The byte string to hash.\\n * @param offset The position to start hashing at.\\n * @param len The number of bytes to hash.\\n * @return The hash of the byte range.\\n */\\n function keccak(\\n bytes memory self,\\n uint256 offset,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n require(offset + len <= self.length);\\n assembly {\\n ret := keccak256(add(add(self, 32), offset), len)\\n }\\n }\\n\\n /*\\n * @dev Returns a positive number if `other` comes lexicographically after\\n * `self`, a negative number if it comes before, or zero if the\\n * contents of the two bytes are equal.\\n * @param self The first bytes to compare.\\n * @param other The second bytes to compare.\\n * @return The result of the comparison.\\n */\\n function compare(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (int256) {\\n return compare(self, 0, self.length, other, 0, other.length);\\n }\\n\\n /*\\n * @dev Returns a positive number if `other` comes lexicographically after\\n * `self`, a negative number if it comes before, or zero if the\\n * contents of the two bytes are equal. Comparison is done per-rune,\\n * on unicode codepoints.\\n * @param self The first bytes to compare.\\n * @param offset The offset of self.\\n * @param len The length of self.\\n * @param other The second bytes to compare.\\n * @param otheroffset The offset of the other string.\\n * @param otherlen The length of the other string.\\n * @return The result of the comparison.\\n */\\n function compare(\\n bytes memory self,\\n uint256 offset,\\n uint256 len,\\n bytes memory other,\\n uint256 otheroffset,\\n uint256 otherlen\\n ) internal pure returns (int256) {\\n if (offset + len > self.length) {\\n revert OffsetOutOfBoundsError(offset + len, self.length);\\n }\\n if (otheroffset + otherlen > other.length) {\\n revert OffsetOutOfBoundsError(otheroffset + otherlen, other.length);\\n }\\n\\n uint256 shortest = len;\\n if (otherlen < len) shortest = otherlen;\\n\\n uint256 selfptr;\\n uint256 otherptr;\\n\\n assembly {\\n selfptr := add(self, add(offset, 32))\\n otherptr := add(other, add(otheroffset, 32))\\n }\\n for (uint256 idx = 0; idx < shortest; idx += 32) {\\n uint256 a;\\n uint256 b;\\n assembly {\\n a := mload(selfptr)\\n b := mload(otherptr)\\n }\\n if (a != b) {\\n // Mask out irrelevant bytes and check again\\n uint256 mask;\\n if (shortest - idx >= 32) {\\n mask = type(uint256).max;\\n } else {\\n mask = ~(2 ** (8 * (idx + 32 - shortest)) - 1);\\n }\\n int256 diff = int256(a & mask) - int256(b & mask);\\n if (diff != 0) return diff;\\n }\\n selfptr += 32;\\n otherptr += 32;\\n }\\n\\n return int256(len) - int256(otherlen);\\n }\\n\\n /*\\n * @dev Returns true if the two byte ranges are equal.\\n * @param self The first byte range to compare.\\n * @param offset The offset into the first byte range.\\n * @param other The second byte range to compare.\\n * @param otherOffset The offset into the second byte range.\\n * @param len The number of bytes to compare\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n uint256 offset,\\n bytes memory other,\\n uint256 otherOffset,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(self, offset, len) == keccak(other, otherOffset, len);\\n }\\n\\n /*\\n * @dev Returns true if the two byte ranges are equal with offsets.\\n * @param self The first byte range to compare.\\n * @param offset The offset into the first byte range.\\n * @param other The second byte range to compare.\\n * @param otherOffset The offset into the second byte range.\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n uint256 offset,\\n bytes memory other,\\n uint256 otherOffset\\n ) internal pure returns (bool) {\\n return\\n keccak(self, offset, self.length - offset) ==\\n keccak(other, otherOffset, other.length - otherOffset);\\n }\\n\\n /*\\n * @dev Compares a range of 'self' to all of 'other' and returns True iff\\n * they are equal.\\n * @param self The first byte range to compare.\\n * @param offset The offset into the first byte range.\\n * @param other The second byte range to compare.\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n uint256 offset,\\n bytes memory other\\n ) internal pure returns (bool) {\\n return\\n self.length == offset + other.length &&\\n equals(self, offset, other, 0, other.length);\\n }\\n\\n /*\\n * @dev Returns true if the two byte ranges are equal.\\n * @param self The first byte range to compare.\\n * @param other The second byte range to compare.\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (bool) {\\n return\\n self.length == other.length &&\\n equals(self, 0, other, 0, self.length);\\n }\\n\\n /*\\n * @dev Returns the 8-bit number at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 8 bits of the string, interpreted as an integer.\\n */\\n function readUint8(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (uint8 ret) {\\n return uint8(self[idx]);\\n }\\n\\n /*\\n * @dev Returns the 16-bit number at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 16 bits of the string, interpreted as an integer.\\n */\\n function readUint16(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (uint16 ret) {\\n require(idx + 2 <= self.length);\\n assembly {\\n ret := and(mload(add(add(self, 2), idx)), 0xFFFF)\\n }\\n }\\n\\n /*\\n * @dev Returns the 32-bit number at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 32 bits of the string, interpreted as an integer.\\n */\\n function readUint32(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (uint32 ret) {\\n require(idx + 4 <= self.length);\\n assembly {\\n ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF)\\n }\\n }\\n\\n /*\\n * @dev Returns the 32 byte value at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 32 bytes of the string.\\n */\\n function readBytes32(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (bytes32 ret) {\\n require(idx + 32 <= self.length);\\n assembly {\\n ret := mload(add(add(self, 32), idx))\\n }\\n }\\n\\n /*\\n * @dev Returns the 32 byte value at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 32 bytes of the string.\\n */\\n function readBytes20(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (bytes20 ret) {\\n require(idx + 20 <= self.length);\\n assembly {\\n ret := and(\\n mload(add(add(self, 32), idx)),\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000\\n )\\n }\\n }\\n\\n /*\\n * @dev Returns the n byte value at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes.\\n * @param len The number of bytes.\\n * @return The specified 32 bytes of the string.\\n */\\n function readBytesN(\\n bytes memory self,\\n uint256 idx,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n require(len <= 32);\\n require(idx + len <= self.length);\\n assembly {\\n let mask := not(sub(exp(256, sub(32, len)), 1))\\n ret := and(mload(add(add(self, 32), idx)), mask)\\n }\\n }\\n\\n function memcpy(uint256 dest, uint256 src, uint256 len) private pure {\\n // Copy word-length chunks while possible\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n // Copy remaining bytes\\n unchecked {\\n uint256 mask = (256 ** (32 - len)) - 1;\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n }\\n\\n /*\\n * @dev Copies a substring into a new byte string.\\n * @param self The byte string to copy from.\\n * @param offset The offset to start copying at.\\n * @param len The number of bytes to copy.\\n */\\n function substring(\\n bytes memory self,\\n uint256 offset,\\n uint256 len\\n ) internal pure returns (bytes memory) {\\n require(offset + len <= self.length);\\n\\n bytes memory ret = new bytes(len);\\n uint256 dest;\\n uint256 src;\\n\\n assembly {\\n dest := add(ret, 32)\\n src := add(add(self, 32), offset)\\n }\\n memcpy(dest, src, len);\\n\\n return ret;\\n }\\n\\n // Maps characters from 0x30 to 0x7A to their base32 values.\\n // 0xFF represents invalid characters in that range.\\n bytes constant base32HexTable =\\n hex\\\"00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\\\";\\n\\n /**\\n * @dev Decodes unpadded base32 data of up to one word in length.\\n * @param self The data to decode.\\n * @param off Offset into the string to start at.\\n * @param len Number of characters to decode.\\n * @return The decoded data, left aligned.\\n */\\n function base32HexDecodeWord(\\n bytes memory self,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32) {\\n require(len <= 52);\\n\\n uint256 ret = 0;\\n uint8 decoded;\\n for (uint256 i = 0; i < len; i++) {\\n bytes1 char = self[off + i];\\n require(char >= 0x30 && char <= 0x7A);\\n decoded = uint8(base32HexTable[uint256(uint8(char)) - 0x30]);\\n require(decoded <= 0x20);\\n if (i == len - 1) {\\n break;\\n }\\n ret = (ret << 5) | decoded;\\n }\\n\\n uint256 bitlen = len * 5;\\n if (len % 8 == 0) {\\n // Multiple of 8 characters, no padding\\n ret = (ret << 5) | decoded;\\n } else if (len % 8 == 2) {\\n // Two extra characters - 1 byte\\n ret = (ret << 3) | (decoded >> 2);\\n bitlen -= 2;\\n } else if (len % 8 == 4) {\\n // Four extra characters - 2 bytes\\n ret = (ret << 1) | (decoded >> 4);\\n bitlen -= 4;\\n } else if (len % 8 == 5) {\\n // Five extra characters - 3 bytes\\n ret = (ret << 4) | (decoded >> 1);\\n bitlen -= 1;\\n } else if (len % 8 == 7) {\\n // Seven extra characters - 4 bytes\\n ret = (ret << 2) | (decoded >> 3);\\n bitlen -= 3;\\n } else {\\n revert();\\n }\\n\\n return bytes32(ret << (256 - bitlen));\\n }\\n\\n /**\\n * @dev Finds the first occurrence of the byte `needle` in `self`.\\n * @param self The string to search\\n * @param off The offset to start searching at\\n * @param len The number of bytes to search\\n * @param needle The byte to search for\\n * @return The offset of `needle` in `self`, or 2**256-1 if it was not found.\\n */\\n function find(\\n bytes memory self,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 idx = off; idx < off + len; idx++) {\\n if (self[idx] == needle) {\\n return idx;\\n }\\n }\\n return type(uint256).max;\\n }\\n}\\n\",\"keccak256\":\"0x4f10902639b85a17ae10745264feff322e793bfb1bc130a9a90efa7dda47c6cc\"},\"contracts/dnssec-oracle/DNSSEC.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\npragma experimental ABIEncoderV2;\\n\\nabstract contract DNSSEC {\\n bytes public anchors;\\n\\n struct RRSetWithSignature {\\n bytes rrset;\\n bytes sig;\\n }\\n\\n event AlgorithmUpdated(uint8 id, address addr);\\n event DigestUpdated(uint8 id, address addr);\\n\\n function verifyRRSet(\\n RRSetWithSignature[] memory input\\n ) external view virtual returns (bytes memory rrs, uint32 inception);\\n\\n function verifyRRSet(\\n RRSetWithSignature[] memory input,\\n uint256 now\\n ) public view virtual returns (bytes memory rrs, uint32 inception);\\n}\\n\",\"keccak256\":\"0xee6a236a59e5db8418c98ee4640a91987d26533c02d305cc6c7a37a3ac4ee907\",\"license\":\"MIT\"},\"contracts/dnssec-oracle/DNSSECImpl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"./Owned.sol\\\";\\nimport \\\"./BytesUtils.sol\\\";\\nimport \\\"./RRUtils.sol\\\";\\nimport \\\"./DNSSEC.sol\\\";\\nimport \\\"./algorithms/Algorithm.sol\\\";\\nimport \\\"./digests/Digest.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\n/*\\n * @dev An oracle contract that verifies and stores DNSSEC-validated DNS records.\\n * @note This differs from the DNSSEC spec defined in RFC4034 and RFC4035 in some key regards:\\n * - NSEC & NSEC3 are not supported; only positive proofs are allowed.\\n * - Proofs involving wildcard names will not validate.\\n * - TTLs on records are ignored, as data is not stored persistently.\\n * - Canonical form of names is not checked; in ENS this is done on the frontend, so submitting\\n * proofs with non-canonical names will only result in registering unresolvable ENS names.\\n */\\ncontract DNSSECImpl is DNSSEC, Owned {\\n using Buffer for Buffer.buffer;\\n using BytesUtils for bytes;\\n using RRUtils for *;\\n\\n uint16 constant DNSCLASS_IN = 1;\\n\\n uint16 constant DNSTYPE_DS = 43;\\n uint16 constant DNSTYPE_DNSKEY = 48;\\n\\n uint256 constant DNSKEY_FLAG_ZONEKEY = 0x100;\\n\\n error InvalidLabelCount(bytes name, uint256 labelsExpected);\\n error SignatureNotValidYet(uint32 inception, uint32 now);\\n error SignatureExpired(uint32 expiration, uint32 now);\\n error InvalidClass(uint16 class);\\n error InvalidRRSet();\\n error SignatureTypeMismatch(uint16 rrsetType, uint16 sigType);\\n error InvalidSignerName(bytes rrsetName, bytes signerName);\\n error InvalidProofType(uint16 proofType);\\n error ProofNameMismatch(bytes signerName, bytes proofName);\\n error NoMatchingProof(bytes signerName);\\n\\n mapping(uint8 => Algorithm) public algorithms;\\n mapping(uint8 => Digest) public digests;\\n\\n /**\\n * @dev Constructor.\\n * @param _anchors The binary format RR entries for the root DS records.\\n */\\n constructor(bytes memory _anchors) {\\n // Insert the 'trust anchors' - the key hashes that start the chain\\n // of trust for all other records.\\n anchors = _anchors;\\n }\\n\\n /**\\n * @dev Sets the contract address for a signature verification algorithm.\\n * Callable only by the owner.\\n * @param id The algorithm ID\\n * @param algo The address of the algorithm contract.\\n */\\n function setAlgorithm(uint8 id, Algorithm algo) public owner_only {\\n algorithms[id] = algo;\\n emit AlgorithmUpdated(id, address(algo));\\n }\\n\\n /**\\n * @dev Sets the contract address for a digest verification algorithm.\\n * Callable only by the owner.\\n * @param id The digest ID\\n * @param digest The address of the digest contract.\\n */\\n function setDigest(uint8 id, Digest digest) public owner_only {\\n digests[id] = digest;\\n emit DigestUpdated(id, address(digest));\\n }\\n\\n /**\\n * @dev Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.\\n * Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.\\n * @param input A list of signed RRSets.\\n * @return rrs The RRData from the last RRSet in the chain.\\n * @return inception The inception time of the signed record set.\\n */\\n function verifyRRSet(\\n RRSetWithSignature[] memory input\\n )\\n external\\n view\\n virtual\\n override\\n returns (bytes memory rrs, uint32 inception)\\n {\\n return verifyRRSet(input, block.timestamp);\\n }\\n\\n /**\\n * @dev Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain.\\n * Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.\\n * @param input A list of signed RRSets.\\n * @param now The Unix timestamp to validate the records at.\\n * @return rrs The RRData from the last RRSet in the chain.\\n * @return inception The inception time of the signed record set.\\n */\\n function verifyRRSet(\\n RRSetWithSignature[] memory input,\\n uint256 now\\n )\\n public\\n view\\n virtual\\n override\\n returns (bytes memory rrs, uint32 inception)\\n {\\n bytes memory proof = anchors;\\n for (uint256 i = 0; i < input.length; i++) {\\n RRUtils.SignedSet memory rrset = validateSignedSet(\\n input[i],\\n proof,\\n now\\n );\\n proof = rrset.data;\\n inception = rrset.inception;\\n }\\n return (proof, inception);\\n }\\n\\n /**\\n * @dev Validates an RRSet against the already trusted RR provided in `proof`.\\n *\\n * @param input The signed RR set. This is in the format described in section\\n * 5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature\\n * data, followed by a series of canonicalised RR records that the signature\\n * applies to.\\n * @param proof The DNSKEY or DS to validate the signature against.\\n * @param now The current timestamp.\\n */\\n function validateSignedSet(\\n RRSetWithSignature memory input,\\n bytes memory proof,\\n uint256 now\\n ) internal view returns (RRUtils.SignedSet memory rrset) {\\n rrset = input.rrset.readSignedSet();\\n\\n // Do some basic checks on the RRs and extract the name\\n bytes memory name = validateRRs(rrset, rrset.typeCovered);\\n if (name.labelCount(0) != rrset.labels) {\\n revert InvalidLabelCount(name, rrset.labels);\\n }\\n rrset.name = name;\\n\\n // All comparisons involving the Signature Expiration and\\n // Inception fields MUST use \\\"serial number arithmetic\\\", as\\n // defined in RFC 1982\\n\\n // o The validator's notion of the current time MUST be less than or\\n // equal to the time listed in the RRSIG RR's Expiration field.\\n if (!RRUtils.serialNumberGte(rrset.expiration, uint32(now))) {\\n revert SignatureExpired(rrset.expiration, uint32(now));\\n }\\n\\n // o The validator's notion of the current time MUST be greater than or\\n // equal to the time listed in the RRSIG RR's Inception field.\\n if (!RRUtils.serialNumberGte(uint32(now), rrset.inception)) {\\n revert SignatureNotValidYet(rrset.inception, uint32(now));\\n }\\n\\n // Validate the signature\\n verifySignature(name, rrset, input, proof);\\n\\n return rrset;\\n }\\n\\n /**\\n * @dev Validates a set of RRs.\\n * @param rrset The RR set.\\n * @param typecovered The type covered by the RRSIG record.\\n */\\n function validateRRs(\\n RRUtils.SignedSet memory rrset,\\n uint16 typecovered\\n ) internal pure returns (bytes memory name) {\\n // Iterate over all the RRs\\n for (\\n RRUtils.RRIterator memory iter = rrset.rrs();\\n !iter.done();\\n iter.next()\\n ) {\\n // We only support class IN (Internet)\\n if (iter.class != DNSCLASS_IN) {\\n revert InvalidClass(iter.class);\\n }\\n\\n if (name.length == 0) {\\n name = iter.name();\\n } else {\\n // Name must be the same on all RRs. We do things this way to avoid copying the name\\n // repeatedly.\\n if (\\n name.length != iter.data.nameLength(iter.offset) ||\\n !name.equals(0, iter.data, iter.offset, name.length)\\n ) {\\n revert InvalidRRSet();\\n }\\n }\\n\\n // o The RRSIG RR's Type Covered field MUST equal the RRset's type.\\n if (iter.dnstype != typecovered) {\\n revert SignatureTypeMismatch(iter.dnstype, typecovered);\\n }\\n }\\n }\\n\\n /**\\n * @dev Performs signature verification.\\n *\\n * Throws or reverts if unable to verify the record.\\n *\\n * @param name The name of the RRSIG record, in DNS label-sequence format.\\n * @param data The original data to verify.\\n * @param proof A DS or DNSKEY record that's already verified by the oracle.\\n */\\n function verifySignature(\\n bytes memory name,\\n RRUtils.SignedSet memory rrset,\\n RRSetWithSignature memory data,\\n bytes memory proof\\n ) internal view {\\n // o The RRSIG RR's Signer's Name field MUST be the name of the zone\\n // that contains the RRset.\\n if (!name.isSubdomainOf(rrset.signerName)) {\\n revert InvalidSignerName(name, rrset.signerName);\\n }\\n\\n RRUtils.RRIterator memory proofRR = proof.iterateRRs(0);\\n // Check the proof\\n if (proofRR.dnstype == DNSTYPE_DS) {\\n verifyWithDS(rrset, data, proofRR);\\n } else if (proofRR.dnstype == DNSTYPE_DNSKEY) {\\n verifyWithKnownKey(rrset, data, proofRR);\\n } else {\\n revert InvalidProofType(proofRR.dnstype);\\n }\\n }\\n\\n /**\\n * @dev Attempts to verify a signed RRSET against an already known public key.\\n * @param rrset The signed set to verify.\\n * @param data The original data the signed set was read from.\\n * @param proof The serialized DS or DNSKEY record to use as proof.\\n */\\n function verifyWithKnownKey(\\n RRUtils.SignedSet memory rrset,\\n RRSetWithSignature memory data,\\n RRUtils.RRIterator memory proof\\n ) internal view {\\n // Check the DNSKEY's owner name matches the signer name on the RRSIG\\n for (; !proof.done(); proof.next()) {\\n bytes memory proofName = proof.name();\\n if (!proofName.equals(rrset.signerName)) {\\n revert ProofNameMismatch(rrset.signerName, proofName);\\n }\\n\\n bytes memory keyrdata = proof.rdata();\\n RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(\\n 0,\\n keyrdata.length\\n );\\n if (verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {\\n return;\\n }\\n }\\n revert NoMatchingProof(rrset.signerName);\\n }\\n\\n /**\\n * @dev Attempts to verify some data using a provided key and a signature.\\n * @param dnskey The dns key record to verify the signature with.\\n * @param rrset The signed RRSET being verified.\\n * @param data The original data `rrset` was decoded from.\\n * @return True iff the key verifies the signature.\\n */\\n function verifySignatureWithKey(\\n RRUtils.DNSKEY memory dnskey,\\n bytes memory keyrdata,\\n RRUtils.SignedSet memory rrset,\\n RRSetWithSignature memory data\\n ) internal view returns (bool) {\\n // TODO: Check key isn't expired, unless updating key itself\\n\\n // The Protocol Field MUST have value 3 (RFC4034 2.1.2)\\n if (dnskey.protocol != 3) {\\n return false;\\n }\\n\\n // o The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST\\n // match the owner name, algorithm, and key tag for some DNSKEY RR in\\n // the zone's apex DNSKEY RRset.\\n if (dnskey.algorithm != rrset.algorithm) {\\n return false;\\n }\\n uint16 computedkeytag = keyrdata.computeKeytag();\\n if (computedkeytag != rrset.keytag) {\\n return false;\\n }\\n\\n // o The matching DNSKEY RR MUST be present in the zone's apex DNSKEY\\n // RRset, and MUST have the Zone Flag bit (DNSKEY RDATA Flag bit 7)\\n // set.\\n if (dnskey.flags & DNSKEY_FLAG_ZONEKEY == 0) {\\n return false;\\n }\\n\\n Algorithm algorithm = algorithms[dnskey.algorithm];\\n if (address(algorithm) == address(0)) {\\n return false;\\n }\\n return algorithm.verify(keyrdata, data.rrset, data.sig);\\n }\\n\\n /**\\n * @dev Attempts to verify a signed RRSET against an already known hash. This function assumes\\n * that the record\\n * @param rrset The signed set to verify.\\n * @param data The original data the signed set was read from.\\n * @param proof The serialized DS or DNSKEY record to use as proof.\\n */\\n function verifyWithDS(\\n RRUtils.SignedSet memory rrset,\\n RRSetWithSignature memory data,\\n RRUtils.RRIterator memory proof\\n ) internal view {\\n uint256 proofOffset = proof.offset;\\n for (\\n RRUtils.RRIterator memory iter = rrset.rrs();\\n !iter.done();\\n iter.next()\\n ) {\\n if (iter.dnstype != DNSTYPE_DNSKEY) {\\n revert InvalidProofType(iter.dnstype);\\n }\\n\\n bytes memory keyrdata = iter.rdata();\\n RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(\\n 0,\\n keyrdata.length\\n );\\n if (verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {\\n // It's self-signed - look for a DS record to verify it.\\n if (\\n verifyKeyWithDS(rrset.signerName, proof, dnskey, keyrdata)\\n ) {\\n return;\\n }\\n // Rewind proof iterator to the start for the next loop iteration.\\n proof.nextOffset = proofOffset;\\n proof.next();\\n }\\n }\\n revert NoMatchingProof(rrset.signerName);\\n }\\n\\n /**\\n * @dev Attempts to verify a key using DS records.\\n * @param keyname The DNS name of the key, in DNS label-sequence format.\\n * @param dsrrs The DS records to use in verification.\\n * @param dnskey The dnskey to verify.\\n * @param keyrdata The RDATA section of the key.\\n * @return True if a DS record verifies this key.\\n */\\n function verifyKeyWithDS(\\n bytes memory keyname,\\n RRUtils.RRIterator memory dsrrs,\\n RRUtils.DNSKEY memory dnskey,\\n bytes memory keyrdata\\n ) internal view returns (bool) {\\n uint16 keytag = keyrdata.computeKeytag();\\n for (; !dsrrs.done(); dsrrs.next()) {\\n bytes memory proofName = dsrrs.name();\\n if (!proofName.equals(keyname)) {\\n revert ProofNameMismatch(keyname, proofName);\\n }\\n\\n RRUtils.DS memory ds = dsrrs.data.readDS(\\n dsrrs.rdataOffset,\\n dsrrs.nextOffset - dsrrs.rdataOffset\\n );\\n if (ds.keytag != keytag) {\\n continue;\\n }\\n if (ds.algorithm != dnskey.algorithm) {\\n continue;\\n }\\n\\n Buffer.buffer memory buf;\\n buf.init(keyname.length + keyrdata.length);\\n buf.append(keyname);\\n buf.append(keyrdata);\\n if (verifyDSHash(ds.digestType, buf.buf, ds.digest)) {\\n return true;\\n }\\n }\\n return false;\\n }\\n\\n /**\\n * @dev Attempts to verify a DS record's hash value against some data.\\n * @param digesttype The digest ID from the DS record.\\n * @param data The data to digest.\\n * @param digest The digest data to check against.\\n * @return True iff the digest matches.\\n */\\n function verifyDSHash(\\n uint8 digesttype,\\n bytes memory data,\\n bytes memory digest\\n ) internal view returns (bool) {\\n if (address(digests[digesttype]) == address(0)) {\\n return false;\\n }\\n return digests[digesttype].verify(data, digest);\\n }\\n}\\n\",\"keccak256\":\"0x671fea3a3332453eecc08c082f264011aa8cfa99fb3c03adf73443843aed5128\",\"license\":\"MIT\"},\"contracts/dnssec-oracle/Owned.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @dev Contract mixin for 'owned' contracts.\\n */\\ncontract Owned {\\n address public owner;\\n\\n modifier owner_only() {\\n require(msg.sender == owner);\\n _;\\n }\\n\\n constructor() public {\\n owner = msg.sender;\\n }\\n\\n function setOwner(address newOwner) public owner_only {\\n owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x49f57dcb9d79015f917e569b4318b766bee9920f72e11a1f5331eabebfc1eb24\"},\"contracts/dnssec-oracle/RRUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./BytesUtils.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\n/**\\n * @dev RRUtils is a library that provides utilities for parsing DNS resource records.\\n */\\nlibrary RRUtils {\\n using BytesUtils for *;\\n using Buffer for *;\\n\\n /**\\n * @dev Returns the number of bytes in the DNS name at 'offset' in 'self'.\\n * @param self The byte array to read a name from.\\n * @param offset The offset to start reading at.\\n * @return The length of the DNS name at 'offset', in bytes.\\n */\\n function nameLength(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (uint256) {\\n uint256 idx = offset;\\n while (true) {\\n assert(idx < self.length);\\n uint256 labelLen = self.readUint8(idx);\\n idx += labelLen + 1;\\n if (labelLen == 0) {\\n break;\\n }\\n }\\n return idx - offset;\\n }\\n\\n /**\\n * @dev Returns a DNS format name at the specified offset of self.\\n * @param self The byte array to read a name from.\\n * @param offset The offset to start reading at.\\n * @return ret The name.\\n */\\n function readName(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (bytes memory ret) {\\n uint256 len = nameLength(self, offset);\\n return self.substring(offset, len);\\n }\\n\\n /**\\n * @dev Returns the number of labels in the DNS name at 'offset' in 'self'.\\n * @param self The byte array to read a name from.\\n * @param offset The offset to start reading at.\\n * @return The number of labels in the DNS name at 'offset', in bytes.\\n */\\n function labelCount(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (uint256) {\\n uint256 count = 0;\\n while (true) {\\n assert(offset < self.length);\\n uint256 labelLen = self.readUint8(offset);\\n offset += labelLen + 1;\\n if (labelLen == 0) {\\n break;\\n }\\n count += 1;\\n }\\n return count;\\n }\\n\\n uint256 constant RRSIG_TYPE = 0;\\n uint256 constant RRSIG_ALGORITHM = 2;\\n uint256 constant RRSIG_LABELS = 3;\\n uint256 constant RRSIG_TTL = 4;\\n uint256 constant RRSIG_EXPIRATION = 8;\\n uint256 constant RRSIG_INCEPTION = 12;\\n uint256 constant RRSIG_KEY_TAG = 16;\\n uint256 constant RRSIG_SIGNER_NAME = 18;\\n\\n struct SignedSet {\\n uint16 typeCovered;\\n uint8 algorithm;\\n uint8 labels;\\n uint32 ttl;\\n uint32 expiration;\\n uint32 inception;\\n uint16 keytag;\\n bytes signerName;\\n bytes data;\\n bytes name;\\n }\\n\\n function readSignedSet(\\n bytes memory data\\n ) internal pure returns (SignedSet memory self) {\\n self.typeCovered = data.readUint16(RRSIG_TYPE);\\n self.algorithm = data.readUint8(RRSIG_ALGORITHM);\\n self.labels = data.readUint8(RRSIG_LABELS);\\n self.ttl = data.readUint32(RRSIG_TTL);\\n self.expiration = data.readUint32(RRSIG_EXPIRATION);\\n self.inception = data.readUint32(RRSIG_INCEPTION);\\n self.keytag = data.readUint16(RRSIG_KEY_TAG);\\n self.signerName = readName(data, RRSIG_SIGNER_NAME);\\n self.data = data.substring(\\n RRSIG_SIGNER_NAME + self.signerName.length,\\n data.length - RRSIG_SIGNER_NAME - self.signerName.length\\n );\\n }\\n\\n function rrs(\\n SignedSet memory rrset\\n ) internal pure returns (RRIterator memory) {\\n return iterateRRs(rrset.data, 0);\\n }\\n\\n /**\\n * @dev An iterator over resource records.\\n */\\n struct RRIterator {\\n bytes data;\\n uint256 offset;\\n uint16 dnstype;\\n uint16 class;\\n uint32 ttl;\\n uint256 rdataOffset;\\n uint256 nextOffset;\\n }\\n\\n /**\\n * @dev Begins iterating over resource records.\\n * @param self The byte string to read from.\\n * @param offset The offset to start reading at.\\n * @return ret An iterator object.\\n */\\n function iterateRRs(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (RRIterator memory ret) {\\n ret.data = self;\\n ret.nextOffset = offset;\\n next(ret);\\n }\\n\\n /**\\n * @dev Returns true iff there are more RRs to iterate.\\n * @param iter The iterator to check.\\n * @return True iff the iterator has finished.\\n */\\n function done(RRIterator memory iter) internal pure returns (bool) {\\n return iter.offset >= iter.data.length;\\n }\\n\\n /**\\n * @dev Moves the iterator to the next resource record.\\n * @param iter The iterator to advance.\\n */\\n function next(RRIterator memory iter) internal pure {\\n iter.offset = iter.nextOffset;\\n if (iter.offset >= iter.data.length) {\\n return;\\n }\\n\\n // Skip the name\\n uint256 off = iter.offset + nameLength(iter.data, iter.offset);\\n\\n // Read type, class, and ttl\\n iter.dnstype = iter.data.readUint16(off);\\n off += 2;\\n iter.class = iter.data.readUint16(off);\\n off += 2;\\n iter.ttl = iter.data.readUint32(off);\\n off += 4;\\n\\n // Read the rdata\\n uint256 rdataLength = iter.data.readUint16(off);\\n off += 2;\\n iter.rdataOffset = off;\\n iter.nextOffset = off + rdataLength;\\n }\\n\\n /**\\n * @dev Returns the name of the current record.\\n * @param iter The iterator.\\n * @return A new bytes object containing the owner name from the RR.\\n */\\n function name(RRIterator memory iter) internal pure returns (bytes memory) {\\n return\\n iter.data.substring(\\n iter.offset,\\n nameLength(iter.data, iter.offset)\\n );\\n }\\n\\n /**\\n * @dev Returns the rdata portion of the current record.\\n * @param iter The iterator.\\n * @return A new bytes object containing the RR's RDATA.\\n */\\n function rdata(\\n RRIterator memory iter\\n ) internal pure returns (bytes memory) {\\n return\\n iter.data.substring(\\n iter.rdataOffset,\\n iter.nextOffset - iter.rdataOffset\\n );\\n }\\n\\n uint256 constant DNSKEY_FLAGS = 0;\\n uint256 constant DNSKEY_PROTOCOL = 2;\\n uint256 constant DNSKEY_ALGORITHM = 3;\\n uint256 constant DNSKEY_PUBKEY = 4;\\n\\n struct DNSKEY {\\n uint16 flags;\\n uint8 protocol;\\n uint8 algorithm;\\n bytes publicKey;\\n }\\n\\n function readDNSKEY(\\n bytes memory data,\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (DNSKEY memory self) {\\n self.flags = data.readUint16(offset + DNSKEY_FLAGS);\\n self.protocol = data.readUint8(offset + DNSKEY_PROTOCOL);\\n self.algorithm = data.readUint8(offset + DNSKEY_ALGORITHM);\\n self.publicKey = data.substring(\\n offset + DNSKEY_PUBKEY,\\n length - DNSKEY_PUBKEY\\n );\\n }\\n\\n uint256 constant DS_KEY_TAG = 0;\\n uint256 constant DS_ALGORITHM = 2;\\n uint256 constant DS_DIGEST_TYPE = 3;\\n uint256 constant DS_DIGEST = 4;\\n\\n struct DS {\\n uint16 keytag;\\n uint8 algorithm;\\n uint8 digestType;\\n bytes digest;\\n }\\n\\n function readDS(\\n bytes memory data,\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (DS memory self) {\\n self.keytag = data.readUint16(offset + DS_KEY_TAG);\\n self.algorithm = data.readUint8(offset + DS_ALGORITHM);\\n self.digestType = data.readUint8(offset + DS_DIGEST_TYPE);\\n self.digest = data.substring(offset + DS_DIGEST, length - DS_DIGEST);\\n }\\n\\n function isSubdomainOf(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (bool) {\\n uint256 off = 0;\\n uint256 counts = labelCount(self, 0);\\n uint256 othercounts = labelCount(other, 0);\\n\\n while (counts > othercounts) {\\n off = progress(self, off);\\n counts--;\\n }\\n\\n return self.equals(off, other, 0);\\n }\\n\\n function compareNames(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (int256) {\\n if (self.equals(other)) {\\n return 0;\\n }\\n\\n uint256 off;\\n uint256 otheroff;\\n uint256 prevoff;\\n uint256 otherprevoff;\\n uint256 counts = labelCount(self, 0);\\n uint256 othercounts = labelCount(other, 0);\\n\\n // Keep removing labels from the front of the name until both names are equal length\\n while (counts > othercounts) {\\n prevoff = off;\\n off = progress(self, off);\\n counts--;\\n }\\n\\n while (othercounts > counts) {\\n otherprevoff = otheroff;\\n otheroff = progress(other, otheroff);\\n othercounts--;\\n }\\n\\n // Compare the last nonequal labels to each other\\n while (counts > 0 && !self.equals(off, other, otheroff)) {\\n prevoff = off;\\n off = progress(self, off);\\n otherprevoff = otheroff;\\n otheroff = progress(other, otheroff);\\n counts -= 1;\\n }\\n\\n if (off == 0) {\\n return -1;\\n }\\n if (otheroff == 0) {\\n return 1;\\n }\\n\\n return\\n self.compare(\\n prevoff + 1,\\n self.readUint8(prevoff),\\n other,\\n otherprevoff + 1,\\n other.readUint8(otherprevoff)\\n );\\n }\\n\\n /**\\n * @dev Compares two serial numbers using RFC1982 serial number math.\\n */\\n function serialNumberGte(\\n uint32 i1,\\n uint32 i2\\n ) internal pure returns (bool) {\\n unchecked {\\n return int32(i1) - int32(i2) >= 0;\\n }\\n }\\n\\n function progress(\\n bytes memory body,\\n uint256 off\\n ) internal pure returns (uint256) {\\n return off + 1 + body.readUint8(off);\\n }\\n\\n /**\\n * @dev Computes the keytag for a chunk of data.\\n * @param data The data to compute a keytag for.\\n * @return The computed key tag.\\n */\\n function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n /* This function probably deserves some explanation.\\n * The DNSSEC keytag function is a checksum that relies on summing up individual bytes\\n * from the input string, with some mild bitshifting. Here's a Naive solidity implementation:\\n *\\n * function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n * uint ac;\\n * for (uint i = 0; i < data.length; i++) {\\n * ac += i & 1 == 0 ? uint16(data.readUint8(i)) << 8 : data.readUint8(i);\\n * }\\n * return uint16(ac + (ac >> 16));\\n * }\\n *\\n * The EVM, with its 256 bit words, is exceedingly inefficient at doing byte-by-byte operations;\\n * the code above, on reasonable length inputs, consumes over 100k gas. But we can make the EVM's\\n * large words work in our favour.\\n *\\n * The code below works by treating the input as a series of 256 bit words. It first masks out\\n * even and odd bytes from each input word, adding them to two separate accumulators `ac1` and `ac2`.\\n * The bytes are separated by empty bytes, so as long as no individual sum exceeds 2^16-1, we're\\n * effectively summing 16 different numbers with each EVM ADD opcode.\\n *\\n * Once it's added up all the inputs, it has to add all the 16 bit values in `ac1` and `ac2` together.\\n * It does this using the same trick - mask out every other value, shift to align them, add them together.\\n * After the first addition on both accumulators, there's enough room to add the two accumulators together,\\n * and the remaining sums can be done just on ac1.\\n */\\n unchecked {\\n require(data.length <= 8192, \\\"Long keys not permitted\\\");\\n uint256 ac1;\\n uint256 ac2;\\n for (uint256 i = 0; i < data.length + 31; i += 32) {\\n uint256 word;\\n assembly {\\n word := mload(add(add(data, 32), i))\\n }\\n if (i + 32 > data.length) {\\n uint256 unused = 256 - (data.length - i) * 8;\\n word = (word >> unused) << unused;\\n }\\n ac1 +=\\n (word &\\n 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >>\\n 8;\\n ac2 += (word &\\n 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF);\\n }\\n ac1 =\\n (ac1 &\\n 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n ((ac1 &\\n 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n 16);\\n ac2 =\\n (ac2 &\\n 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n ((ac2 &\\n 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n 16);\\n ac1 = (ac1 << 8) + ac2;\\n ac1 =\\n (ac1 &\\n 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) +\\n ((ac1 &\\n 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >>\\n 32);\\n ac1 =\\n (ac1 &\\n 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) +\\n ((ac1 &\\n 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >>\\n 64);\\n ac1 =\\n (ac1 &\\n 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +\\n (ac1 >> 128);\\n ac1 += (ac1 >> 16) & 0xFFFF;\\n return uint16(ac1);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x4dd68a6efd7c38f6b0e95ca0c056ecb74f88583da650b1a8639e6e78be36fede\"},\"contracts/dnssec-oracle/algorithms/Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\\n */\\ninterface Algorithm {\\n /**\\n * @dev Verifies a signature.\\n * @param key The public key to verify with.\\n * @param data The signed data to verify.\\n * @param signature The signature to verify.\\n * @return True iff the signature is valid.\\n */\\n function verify(\\n bytes calldata key,\\n bytes calldata data,\\n bytes calldata signature\\n ) external view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xaf6825f9852c69f8e36540821d067b4550dd2263497af9d645309b6a0c457ba6\"},\"contracts/dnssec-oracle/digests/Digest.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @dev An interface for contracts implementing a DNSSEC digest.\\n */\\ninterface Digest {\\n /**\\n * @dev Verifies a cryptographic hash.\\n * @param data The data to hash.\\n * @param hash The hash to compare to.\\n * @return True iff the hashed data matches the provided hash value.\\n */\\n function verify(\\n bytes calldata data,\\n bytes calldata hash\\n ) external pure virtual returns (bool);\\n}\\n\",\"keccak256\":\"0x8ea926b2db0578c4ad7fce4582fc0f6f0f9efee8dca2085dbdb9984f18941e28\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b506040516200205638038062002056833981016040819052620000349162000072565b600180546001600160a01b031916331790556000620000548282620001d6565b5050620002a2565b634e487b7160e01b600052604160045260246000fd5b600060208083850312156200008657600080fd5b82516001600160401b03808211156200009e57600080fd5b818501915085601f830112620000b357600080fd5b815181811115620000c857620000c86200005c565b604051601f8201601f19908116603f01168101908382118183101715620000f357620000f36200005c565b8160405282815288868487010111156200010c57600080fd5b600093505b8284101562000130578484018601518185018701529285019262000111565b600086848301015280965050505050505092915050565b600181811c908216806200015c57607f821691505b6020821081036200017d57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001d157600081815260208120601f850160051c81016020861015620001ac5750805b601f850160051c820191505b81811015620001cd57828155600101620001b8565b5050505b505050565b81516001600160401b03811115620001f257620001f26200005c565b6200020a8162000203845462000147565b8462000183565b602080601f831160018114620002425760008415620002295750858301515b600019600386901b1c1916600185901b178555620001cd565b600085815260208120601f198616915b82811015620002735788860151825594840194600190910190840162000252565b5085821015620002925787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b611da480620002b26000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c806373cc48a61161007657806398d35f201161005b57806398d35f2014610161578063bdf95fef14610176578063c327deef1461018957600080fd5b806373cc48a61461010d5780638da5cb5b1461014e57600080fd5b8063020ed8d3146100a857806313af4035146100bd57806328e7677d146100d0578063440f3d42146100e3575b600080fd5b6100bb6100b6366004611871565b6101b2565b005b6100bb6100cb3660046118a8565b610241565b6100bb6100de366004611871565b610287565b6100f66100f1366004611a9f565b61030e565b604051610104929190611b2a565b60405180910390f35b61013661011b366004611b52565b6003602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610104565b600154610136906001600160a01b031681565b610169610400565b6040516101049190611b6d565b6100f6610184366004611b80565b61048e565b610136610197366004611b52565b6002602052600090815260409020546001600160a01b031681565b6001546001600160a01b031633146101c957600080fd5b60ff8216600081815260026020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0386169081179091558251938452908301527ff73c3c226af96b7f1ba666a21b3ceaf2be3ee6a365e3178fd9cd1eaae0075aa891015b60405180910390a15050565b6001546001600160a01b0316331461025857600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001546001600160a01b0316331461029e57600080fd5b60ff8216600081815260036020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0386169081179091558251938452908301527f2fcc274c3b72dd483ab201bfa87295e3817e8b9b10693219873b722ca1af00c79101610235565b60606000806000805461032090611bb5565b80601f016020809104026020016040519081016040528092919081815260200182805461034c90611bb5565b80156103995780601f1061036e57610100808354040283529160200191610399565b820191906000526020600020905b81548152906001019060200180831161037c57829003601f168201915b5050505050905060005b85518110156103f65760006103d28783815181106103c3576103c3611bef565b602002602001015184886104a5565b61010081015160a090910151945092508190506103ee81611c1b565b9150506103a3565b5091509250929050565b6000805461040d90611bb5565b80601f016020809104026020016040519081016040528092919081815260200182805461043990611bb5565b80156104865780601f1061045b57610100808354040283529160200191610486565b820191906000526020600020905b81548152906001019060200180831161046957829003601f168201915b505050505081565b6060600061049c834261030e565b91509150915091565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c082019290925260e081018290526101008101829052610120810191909152835161050390610647565b90506000610515828360000151610789565b604083015190915060ff1661052b8260006108e6565b14610573578082604001516040517fe861b2bd00000000000000000000000000000000000000000000000000000000815260040161056a929190611c34565b60405180910390fd5b6101208201819052608082015160009084900360030b12156105d75760808201516040517fa784f87e00000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161056a565b60a0820151600090840360030b12156106325760a08201516040517fbd41036a00000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161056a565b61063e8183878761094c565b505b9392505050565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018190526101008201819052610120820152906106a2908390610a16565b61ffff1681526106b3826002610a3e565b60ff1660208201526106c6826003610a3e565b60ff1660408201526106d9826004610a62565b63ffffffff90811660608301526106f5908390600890610a6216565b63ffffffff9081166080830152610711908390600c90610a6216565b63ffffffff90811660a083015261072d908390601090610a1616565b61ffff1660c0820152610741826012610a8c565b60e082018190525161077e90610758906012611c59565b8260e00151516012855161076c9190611c6c565b6107769190611c6c565b849190610aaf565b610100820152919050565b6060600061079684610b31565b90505b805151602082015110156108df57606081015161ffff166001146107f55760608101516040517f98a5f31a00000000000000000000000000000000000000000000000000000000815261ffff909116600482015260240161056a565b815160000361080e5761080781610b8f565b9150610878565b6020810151815161081e91610bb0565b8251141580610841575080516020820151835161083f928592600092610c0a565b155b15610878576040517fcbceee6f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8261ffff16816040015161ffff16146108d15760408082015190517fa6ff8a8a00000000000000000000000000000000000000000000000000000000815261ffff9182166004820152908416602482015260440161056a565b6108da81610c2d565b610799565b5092915050565b6000805b835183106108fa576108fa611c7f565b60006109068585610a3e565b60ff169050610916816001611c59565b6109209085611c59565b9350806000036109305750610943565b61093b600183611c59565b9150506108ea565b90505b92915050565b60e083015161095c908590610d15565b6109995760e08301516040517feaafc59b00000000000000000000000000000000000000000000000000000000815261056a918691600401611c95565b60006109a58282610d72565b9050602b61ffff16816040015161ffff16036109cb576109c6848483610dd3565b610a0f565b603061ffff16816040015161ffff16036109ea576109c6848483610ec0565b60408082015190516361529e8760e01b815261ffff909116600482015260240161056a565b5050505050565b8151600090610a26836002611c59565b1115610a3157600080fd5b50016002015161ffff1690565b6000828281518110610a5257610a52611bef565b016020015160f81c905092915050565b8151600090610a72836004611c59565b1115610a7d57600080fd5b50016004015163ffffffff1690565b60606000610a9a8484610bb0565b9050610aa7848483610aaf565b949350505050565b8251606090610abe8385611c59565b1115610ac957600080fd5b60008267ffffffffffffffff811115610ae457610ae46118c5565b6040519080825280601f01601f191660200182016040528015610b0e576020820181803683370190505b50905060208082019086860101610b26828287610f88565b509095945050505050565b610b7f6040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b6109468261010001516000610d72565b6020810151815160609161094691610ba79082610bb0565b84519190610aaf565b6000815b83518110610bc457610bc4611c7f565b6000610bd08583610a3e565b60ff169050610be0816001611c59565b610bea9083611c59565b915080600003610bfa5750610c00565b50610bb4565b610aa78382611c6c565b6000610c17848484610fde565b610c22878785610fde565b149695505050505050565b60c08101516020820181905281515111610c445750565b6000610c5882600001518360200151610bb0565b8260200151610c679190611c59565b8251909150610c769082610a16565b61ffff166040830152610c8a600282611c59565b8251909150610c999082610a16565b61ffff166060830152610cad600282611c59565b8251909150610cbc9082610a62565b63ffffffff166080830152610cd2600482611c59565b8251909150600090610ce49083610a16565b61ffff169050610cf5600283611c59565b60a084018190529150610d088183611c59565b60c0909301929092525050565b60008080610d2385826108e6565b90506000610d328560006108e6565b90505b80821115610d5b57610d478684611002565b925081610d5381611cc3565b925050610d35565b610d688684876000611026565b9695505050505050565b610dc06040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261094681610c2d565b60208101516000610de385610b31565b90505b80515160208201511015610ea057604081015161ffff16603014610e295760408082015190516361529e8760e01b815261ffff909116600482015260240161056a565b6000610e348261105b565b90506000610e4f60008351846110779092919063ffffffff16565b9050610e5d81838989611115565b15610e9057610e728760e00151868385611254565b15610e805750505050505050565b60c08501849052610e9085610c2d565b5050610e9b81610c2d565b610de6565b508360e001516040516306cde0f360e01b815260040161056a9190611b6d565b80515160208201511015610f69576000610ed982610b8f565b9050610ef28460e001518261139190919063ffffffff16565b610f17578360e0015181604051636b80573f60e11b815260040161056a929190611c95565b6000610f228361105b565b90506000610f3d60008351846110779092919063ffffffff16565b9050610f4b81838888611115565b15610f5857505050505050565b505050610f6481610c2d565b610ec0565b8260e001516040516306cde0f360e01b815260040161056a9190611b6d565b60208110610fc05781518352610f9f602084611c59565b9250610fac602083611c59565b9150610fb9602082611c6c565b9050610f88565b905182516020929092036101000a6000190180199091169116179052565b8251600090610fed8385611c59565b1115610ff857600080fd5b5091016020012090565b600061100e8383610a3e565b60ff1661101c836001611c59565b6109439190611c59565b600061103f838384865161103a9190611c6c565b610fde565b611051868687895161103a9190611c6c565b1495945050505050565b60a081015160c082015160609161094691610ba7908290611c6c565b60408051608081018252600080825260208201819052918101919091526060808201526110af6110a8600085611c59565b8590610a16565b61ffff1681526110ca6110c3600285611c59565b8590610a3e565b60ff1660208201526110e06110c3600385611c59565b60ff1660408201526111096110f6600485611c59565b611101600485611c6c565b869190610aaf565b60608201529392505050565b6000846020015160ff1660031461112e57506000610aa7565b826020015160ff16856040015160ff161461114b57506000610aa7565b6000611156856113af565b90508360c0015161ffff168161ffff1614611175576000915050610aa7565b85516101001660000361118c576000915050610aa7565b60408087015160ff166000908152600260205220546001600160a01b0316806111ba57600092505050610aa7565b835160208501516040517fde8f50a10000000000000000000000000000000000000000000000000000000081526001600160a01b0384169263de8f50a192611208928b929190600401611cda565b602060405180830381865afa158015611225573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112499190611d13565b979650505050505050565b600080611260836113af565b90505b8451516020860151101561138557600061127c86610b8f565b90506112888188611391565b6112a9578681604051636b80573f60e11b815260040161056a929190611c95565b60a086015160c08701516000916112ce916112c5908290611c6c565b89519190611077565b90508261ffff16816000015161ffff16146112ea575050611377565b856040015160ff16816020015160ff1614611306575050611377565b60408051808201909152606081526000602082015261133386518a5161132c9190611c59565b82906115f3565b5061133e818a61166a565b50611349818761166a565b5061136182604001518260000151846060015161168b565b15611373576001945050505050610aa7565b5050505b61138085610c2d565b611263565b50600095945050505050565b60008151835114801561094357506109438360008460008751610c0a565b60006120008251111561141e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4c6f6e67206b657973206e6f74207065726d6974746564000000000000000000604482015260640161056a565b60008060005b8451601f0181101561149357600081602087010151905085518260200111156114595785518290036008026101000390811c901b5b7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff600882901c81169490940193169190910190602001611424565b506010827fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff000016901c827dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff160191506010817fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff000016901c817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff1601905080600883901b0191506020827fffffffff00000000ffffffff00000000ffffffff00000000ffffffff0000000016901c827bffffffff00000000ffffffff00000000ffffffff00000000ffffffff160191506040827fffffffffffffffff0000000000000000ffffffffffffffff000000000000000016901c8277ffffffffffffffff0000000000000000ffffffffffffffff16019150608082901c826fffffffffffffffffffffffffffffffff16019150601082901c61ffff16820191508192505050919050565b604080518082019091526060815260006020820152611613602083611d35565b1561163b57611623602083611d35565b61162e906020611c6c565b6116389083611c59565b91505b60208084018390526040518085526000815290818401018181101561165f57600080fd5b604052509192915050565b60408051808201909152606081526000602082015261094383838451611750565b60ff83166000908152600360205260408120546001600160a01b03166116b357506000610640565b60ff8416600090815260036020526040908190205490517ff7e83aee0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063f7e83aee9061170f9086908690600401611c95565b602060405180830381865afa15801561172c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa79190611d13565b604080518082019091526060815260006020820152825182111561177357600080fd5b83515160006117828483611c59565b905085602001518111156117a4576117a48661179f836002611d57565b611826565b8551805183820160200191600091808511156117be578482525b505050602086015b602086106117fe57805182526117dd602083611c59565b91506117ea602082611c59565b90506117f7602087611c6c565b95506117c6565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b815161183283836115f3565b5061183d838261166a565b50505050565b803560ff8116811461185457600080fd5b919050565b6001600160a01b038116811461186e57600080fd5b50565b6000806040838503121561188457600080fd5b61188d83611843565b9150602083013561189d81611859565b809150509250929050565b6000602082840312156118ba57600080fd5b813561094381611859565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156118fe576118fe6118c5565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561192d5761192d6118c5565b604052919050565b600082601f83011261194657600080fd5b813567ffffffffffffffff811115611960576119606118c5565b611973601f8201601f1916602001611904565b81815284602083860101111561198857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126119b657600080fd5b8135602067ffffffffffffffff808311156119d3576119d36118c5565b8260051b6119e2838201611904565b93845285810183019383810190888611156119fc57600080fd5b84880192505b85831015611a9357823584811115611a1a5760008081fd5b88016040818b03601f1901811315611a325760008081fd5b611a3a6118db565b8783013587811115611a4c5760008081fd5b611a5a8d8a83870101611935565b825250908201359086821115611a705760008081fd5b611a7e8c8984860101611935565b81890152845250509184019190840190611a02565b98975050505050505050565b60008060408385031215611ab257600080fd5b823567ffffffffffffffff811115611ac957600080fd5b611ad5858286016119a5565b95602094909401359450505050565b6000815180845260005b81811015611b0a57602081850181015186830182015201611aee565b506000602082860101526020601f19601f83011685010191505092915050565b604081526000611b3d6040830185611ae4565b905063ffffffff831660208301529392505050565b600060208284031215611b6457600080fd5b61094382611843565b6020815260006109436020830184611ae4565b600060208284031215611b9257600080fd5b813567ffffffffffffffff811115611ba957600080fd5b610aa7848285016119a5565b600181811c90821680611bc957607f821691505b602082108103611be957634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611c2d57611c2d611c05565b5060010190565b604081526000611c476040830185611ae4565b905060ff831660208301529392505050565b8082018082111561094657610946611c05565b8181038181111561094657610946611c05565b634e487b7160e01b600052600160045260246000fd5b604081526000611ca86040830185611ae4565b8281036020840152611cba8185611ae4565b95945050505050565b600081611cd257611cd2611c05565b506000190190565b606081526000611ced6060830186611ae4565b8281036020840152611cff8186611ae4565b90508281036040840152610d688185611ae4565b600060208284031215611d2557600080fd5b8151801515811461094357600080fd5b600082611d5257634e487b7160e01b600052601260045260246000fd5b500690565b808202811582820484141761094657610946611c0556fea2646970667358221220a36fa1213f53338776d2c9565e9a8b3482299a2c13495ac6aaeebf00585273ff64736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a35760003560e01c806373cc48a61161007657806398d35f201161005b57806398d35f2014610161578063bdf95fef14610176578063c327deef1461018957600080fd5b806373cc48a61461010d5780638da5cb5b1461014e57600080fd5b8063020ed8d3146100a857806313af4035146100bd57806328e7677d146100d0578063440f3d42146100e3575b600080fd5b6100bb6100b6366004611871565b6101b2565b005b6100bb6100cb3660046118a8565b610241565b6100bb6100de366004611871565b610287565b6100f66100f1366004611a9f565b61030e565b604051610104929190611b2a565b60405180910390f35b61013661011b366004611b52565b6003602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610104565b600154610136906001600160a01b031681565b610169610400565b6040516101049190611b6d565b6100f6610184366004611b80565b61048e565b610136610197366004611b52565b6002602052600090815260409020546001600160a01b031681565b6001546001600160a01b031633146101c957600080fd5b60ff8216600081815260026020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0386169081179091558251938452908301527ff73c3c226af96b7f1ba666a21b3ceaf2be3ee6a365e3178fd9cd1eaae0075aa891015b60405180910390a15050565b6001546001600160a01b0316331461025857600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001546001600160a01b0316331461029e57600080fd5b60ff8216600081815260036020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0386169081179091558251938452908301527f2fcc274c3b72dd483ab201bfa87295e3817e8b9b10693219873b722ca1af00c79101610235565b60606000806000805461032090611bb5565b80601f016020809104026020016040519081016040528092919081815260200182805461034c90611bb5565b80156103995780601f1061036e57610100808354040283529160200191610399565b820191906000526020600020905b81548152906001019060200180831161037c57829003601f168201915b5050505050905060005b85518110156103f65760006103d28783815181106103c3576103c3611bef565b602002602001015184886104a5565b61010081015160a090910151945092508190506103ee81611c1b565b9150506103a3565b5091509250929050565b6000805461040d90611bb5565b80601f016020809104026020016040519081016040528092919081815260200182805461043990611bb5565b80156104865780601f1061045b57610100808354040283529160200191610486565b820191906000526020600020905b81548152906001019060200180831161046957829003601f168201915b505050505081565b6060600061049c834261030e565b91509150915091565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c082019290925260e081018290526101008101829052610120810191909152835161050390610647565b90506000610515828360000151610789565b604083015190915060ff1661052b8260006108e6565b14610573578082604001516040517fe861b2bd00000000000000000000000000000000000000000000000000000000815260040161056a929190611c34565b60405180910390fd5b6101208201819052608082015160009084900360030b12156105d75760808201516040517fa784f87e00000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161056a565b60a0820151600090840360030b12156106325760a08201516040517fbd41036a00000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161056a565b61063e8183878761094c565b505b9392505050565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018190526101008201819052610120820152906106a2908390610a16565b61ffff1681526106b3826002610a3e565b60ff1660208201526106c6826003610a3e565b60ff1660408201526106d9826004610a62565b63ffffffff90811660608301526106f5908390600890610a6216565b63ffffffff9081166080830152610711908390600c90610a6216565b63ffffffff90811660a083015261072d908390601090610a1616565b61ffff1660c0820152610741826012610a8c565b60e082018190525161077e90610758906012611c59565b8260e00151516012855161076c9190611c6c565b6107769190611c6c565b849190610aaf565b610100820152919050565b6060600061079684610b31565b90505b805151602082015110156108df57606081015161ffff166001146107f55760608101516040517f98a5f31a00000000000000000000000000000000000000000000000000000000815261ffff909116600482015260240161056a565b815160000361080e5761080781610b8f565b9150610878565b6020810151815161081e91610bb0565b8251141580610841575080516020820151835161083f928592600092610c0a565b155b15610878576040517fcbceee6f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8261ffff16816040015161ffff16146108d15760408082015190517fa6ff8a8a00000000000000000000000000000000000000000000000000000000815261ffff9182166004820152908416602482015260440161056a565b6108da81610c2d565b610799565b5092915050565b6000805b835183106108fa576108fa611c7f565b60006109068585610a3e565b60ff169050610916816001611c59565b6109209085611c59565b9350806000036109305750610943565b61093b600183611c59565b9150506108ea565b90505b92915050565b60e083015161095c908590610d15565b6109995760e08301516040517feaafc59b00000000000000000000000000000000000000000000000000000000815261056a918691600401611c95565b60006109a58282610d72565b9050602b61ffff16816040015161ffff16036109cb576109c6848483610dd3565b610a0f565b603061ffff16816040015161ffff16036109ea576109c6848483610ec0565b60408082015190516361529e8760e01b815261ffff909116600482015260240161056a565b5050505050565b8151600090610a26836002611c59565b1115610a3157600080fd5b50016002015161ffff1690565b6000828281518110610a5257610a52611bef565b016020015160f81c905092915050565b8151600090610a72836004611c59565b1115610a7d57600080fd5b50016004015163ffffffff1690565b60606000610a9a8484610bb0565b9050610aa7848483610aaf565b949350505050565b8251606090610abe8385611c59565b1115610ac957600080fd5b60008267ffffffffffffffff811115610ae457610ae46118c5565b6040519080825280601f01601f191660200182016040528015610b0e576020820181803683370190505b50905060208082019086860101610b26828287610f88565b509095945050505050565b610b7f6040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b6109468261010001516000610d72565b6020810151815160609161094691610ba79082610bb0565b84519190610aaf565b6000815b83518110610bc457610bc4611c7f565b6000610bd08583610a3e565b60ff169050610be0816001611c59565b610bea9083611c59565b915080600003610bfa5750610c00565b50610bb4565b610aa78382611c6c565b6000610c17848484610fde565b610c22878785610fde565b149695505050505050565b60c08101516020820181905281515111610c445750565b6000610c5882600001518360200151610bb0565b8260200151610c679190611c59565b8251909150610c769082610a16565b61ffff166040830152610c8a600282611c59565b8251909150610c999082610a16565b61ffff166060830152610cad600282611c59565b8251909150610cbc9082610a62565b63ffffffff166080830152610cd2600482611c59565b8251909150600090610ce49083610a16565b61ffff169050610cf5600283611c59565b60a084018190529150610d088183611c59565b60c0909301929092525050565b60008080610d2385826108e6565b90506000610d328560006108e6565b90505b80821115610d5b57610d478684611002565b925081610d5381611cc3565b925050610d35565b610d688684876000611026565b9695505050505050565b610dc06040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261094681610c2d565b60208101516000610de385610b31565b90505b80515160208201511015610ea057604081015161ffff16603014610e295760408082015190516361529e8760e01b815261ffff909116600482015260240161056a565b6000610e348261105b565b90506000610e4f60008351846110779092919063ffffffff16565b9050610e5d81838989611115565b15610e9057610e728760e00151868385611254565b15610e805750505050505050565b60c08501849052610e9085610c2d565b5050610e9b81610c2d565b610de6565b508360e001516040516306cde0f360e01b815260040161056a9190611b6d565b80515160208201511015610f69576000610ed982610b8f565b9050610ef28460e001518261139190919063ffffffff16565b610f17578360e0015181604051636b80573f60e11b815260040161056a929190611c95565b6000610f228361105b565b90506000610f3d60008351846110779092919063ffffffff16565b9050610f4b81838888611115565b15610f5857505050505050565b505050610f6481610c2d565b610ec0565b8260e001516040516306cde0f360e01b815260040161056a9190611b6d565b60208110610fc05781518352610f9f602084611c59565b9250610fac602083611c59565b9150610fb9602082611c6c565b9050610f88565b905182516020929092036101000a6000190180199091169116179052565b8251600090610fed8385611c59565b1115610ff857600080fd5b5091016020012090565b600061100e8383610a3e565b60ff1661101c836001611c59565b6109439190611c59565b600061103f838384865161103a9190611c6c565b610fde565b611051868687895161103a9190611c6c565b1495945050505050565b60a081015160c082015160609161094691610ba7908290611c6c565b60408051608081018252600080825260208201819052918101919091526060808201526110af6110a8600085611c59565b8590610a16565b61ffff1681526110ca6110c3600285611c59565b8590610a3e565b60ff1660208201526110e06110c3600385611c59565b60ff1660408201526111096110f6600485611c59565b611101600485611c6c565b869190610aaf565b60608201529392505050565b6000846020015160ff1660031461112e57506000610aa7565b826020015160ff16856040015160ff161461114b57506000610aa7565b6000611156856113af565b90508360c0015161ffff168161ffff1614611175576000915050610aa7565b85516101001660000361118c576000915050610aa7565b60408087015160ff166000908152600260205220546001600160a01b0316806111ba57600092505050610aa7565b835160208501516040517fde8f50a10000000000000000000000000000000000000000000000000000000081526001600160a01b0384169263de8f50a192611208928b929190600401611cda565b602060405180830381865afa158015611225573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112499190611d13565b979650505050505050565b600080611260836113af565b90505b8451516020860151101561138557600061127c86610b8f565b90506112888188611391565b6112a9578681604051636b80573f60e11b815260040161056a929190611c95565b60a086015160c08701516000916112ce916112c5908290611c6c565b89519190611077565b90508261ffff16816000015161ffff16146112ea575050611377565b856040015160ff16816020015160ff1614611306575050611377565b60408051808201909152606081526000602082015261133386518a5161132c9190611c59565b82906115f3565b5061133e818a61166a565b50611349818761166a565b5061136182604001518260000151846060015161168b565b15611373576001945050505050610aa7565b5050505b61138085610c2d565b611263565b50600095945050505050565b60008151835114801561094357506109438360008460008751610c0a565b60006120008251111561141e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4c6f6e67206b657973206e6f74207065726d6974746564000000000000000000604482015260640161056a565b60008060005b8451601f0181101561149357600081602087010151905085518260200111156114595785518290036008026101000390811c901b5b7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff600882901c81169490940193169190910190602001611424565b506010827fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff000016901c827dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff160191506010817fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff000016901c817dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff1601905080600883901b0191506020827fffffffff00000000ffffffff00000000ffffffff00000000ffffffff0000000016901c827bffffffff00000000ffffffff00000000ffffffff00000000ffffffff160191506040827fffffffffffffffff0000000000000000ffffffffffffffff000000000000000016901c8277ffffffffffffffff0000000000000000ffffffffffffffff16019150608082901c826fffffffffffffffffffffffffffffffff16019150601082901c61ffff16820191508192505050919050565b604080518082019091526060815260006020820152611613602083611d35565b1561163b57611623602083611d35565b61162e906020611c6c565b6116389083611c59565b91505b60208084018390526040518085526000815290818401018181101561165f57600080fd5b604052509192915050565b60408051808201909152606081526000602082015261094383838451611750565b60ff83166000908152600360205260408120546001600160a01b03166116b357506000610640565b60ff8416600090815260036020526040908190205490517ff7e83aee0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063f7e83aee9061170f9086908690600401611c95565b602060405180830381865afa15801561172c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa79190611d13565b604080518082019091526060815260006020820152825182111561177357600080fd5b83515160006117828483611c59565b905085602001518111156117a4576117a48661179f836002611d57565b611826565b8551805183820160200191600091808511156117be578482525b505050602086015b602086106117fe57805182526117dd602083611c59565b91506117ea602082611c59565b90506117f7602087611c6c565b95506117c6565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b815161183283836115f3565b5061183d838261166a565b50505050565b803560ff8116811461185457600080fd5b919050565b6001600160a01b038116811461186e57600080fd5b50565b6000806040838503121561188457600080fd5b61188d83611843565b9150602083013561189d81611859565b809150509250929050565b6000602082840312156118ba57600080fd5b813561094381611859565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156118fe576118fe6118c5565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561192d5761192d6118c5565b604052919050565b600082601f83011261194657600080fd5b813567ffffffffffffffff811115611960576119606118c5565b611973601f8201601f1916602001611904565b81815284602083860101111561198857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126119b657600080fd5b8135602067ffffffffffffffff808311156119d3576119d36118c5565b8260051b6119e2838201611904565b93845285810183019383810190888611156119fc57600080fd5b84880192505b85831015611a9357823584811115611a1a5760008081fd5b88016040818b03601f1901811315611a325760008081fd5b611a3a6118db565b8783013587811115611a4c5760008081fd5b611a5a8d8a83870101611935565b825250908201359086821115611a705760008081fd5b611a7e8c8984860101611935565b81890152845250509184019190840190611a02565b98975050505050505050565b60008060408385031215611ab257600080fd5b823567ffffffffffffffff811115611ac957600080fd5b611ad5858286016119a5565b95602094909401359450505050565b6000815180845260005b81811015611b0a57602081850181015186830182015201611aee565b506000602082860101526020601f19601f83011685010191505092915050565b604081526000611b3d6040830185611ae4565b905063ffffffff831660208301529392505050565b600060208284031215611b6457600080fd5b61094382611843565b6020815260006109436020830184611ae4565b600060208284031215611b9257600080fd5b813567ffffffffffffffff811115611ba957600080fd5b610aa7848285016119a5565b600181811c90821680611bc957607f821691505b602082108103611be957634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611c2d57611c2d611c05565b5060010190565b604081526000611c476040830185611ae4565b905060ff831660208301529392505050565b8082018082111561094657610946611c05565b8181038181111561094657610946611c05565b634e487b7160e01b600052600160045260246000fd5b604081526000611ca86040830185611ae4565b8281036020840152611cba8185611ae4565b95945050505050565b600081611cd257611cd2611c05565b506000190190565b606081526000611ced6060830186611ae4565b8281036020840152611cff8186611ae4565b90508281036040840152610d688185611ae4565b600060208284031215611d2557600080fd5b8151801515811461094357600080fd5b600082611d5257634e487b7160e01b600052601260045260246000fd5b500690565b808202811582820484141761094657610946611c0556fea2646970667358221220a36fa1213f53338776d2c9565e9a8b3482299a2c13495ac6aaeebf00585273ff64736f6c63430008110033", + "devdoc": { + "kind": "dev", + "methods": { + "constructor": { + "details": "Constructor.", + "params": { + "_anchors": "The binary format RR entries for the root DS records." + } + }, + "setAlgorithm(uint8,address)": { + "details": "Sets the contract address for a signature verification algorithm. Callable only by the owner.", + "params": { + "algo": "The address of the algorithm contract.", + "id": "The algorithm ID" + } + }, + "setDigest(uint8,address)": { + "details": "Sets the contract address for a digest verification algorithm. Callable only by the owner.", + "params": { + "digest": "The address of the digest contract.", + "id": "The digest ID" + } + }, + "verifyRRSet((bytes,bytes)[])": { + "details": "Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain. Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.", + "params": { + "input": "A list of signed RRSets." + }, + "returns": { + "inception": "The inception time of the signed record set.", + "rrs": "The RRData from the last RRSet in the chain." + } + }, + "verifyRRSet((bytes,bytes)[],uint256)": { + "details": "Takes a chain of signed DNS records, verifies them, and returns the data from the last record set in the chain. Reverts if the records do not form an unbroken chain of trust to the DNSSEC anchor records.", + "params": { + "input": "A list of signed RRSets.", + "now": "The Unix timestamp to validate the records at." + }, + "returns": { + "inception": "The inception time of the signed record set.", + "rrs": "The RRData from the last RRSet in the chain." + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6638, + "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl", + "label": "anchors", + "offset": 0, + "slot": "0", + "type": "t_bytes_storage" + }, + { + "astId": 7615, + "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl", + "label": "owner", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 6770, + "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl", + "label": "algorithms", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint8,t_contract(Algorithm)8778)" + }, + { + "astId": 6775, + "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl", + "label": "digests", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint8,t_contract(Digest)10619)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes_storage": { + "encoding": "bytes", + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(Algorithm)8778": { + "encoding": "inplace", + "label": "contract Algorithm", + "numberOfBytes": "20" + }, + "t_contract(Digest)10619": { + "encoding": "inplace", + "label": "contract Digest", + "numberOfBytes": "20" + }, + "t_mapping(t_uint8,t_contract(Algorithm)8778)": { + "encoding": "mapping", + "key": "t_uint8", + "label": "mapping(uint8 => contract Algorithm)", + "numberOfBytes": "32", + "value": "t_contract(Algorithm)8778" + }, + "t_mapping(t_uint8,t_contract(Digest)10619)": { + "encoding": "mapping", + "key": "t_uint8", + "label": "mapping(uint8 => contract Digest)", + "numberOfBytes": "32", + "value": "t_contract(Digest)10619" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/sepolia/DummyAlgorithm.json b/deployments/sepolia/DummyAlgorithm.json new file mode 100644 index 00000000..9ad8222d --- /dev/null +++ b/deployments/sepolia/DummyAlgorithm.json @@ -0,0 +1,71 @@ +{ + "address": "0x4b2e688BB54DD406b6EF795064126d9A4D3d728D", + "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" + } + ], + "transactionHash": "0xdbad7c40098717e179617f82fe91223795ca52a33dd605e5afed40cfafabbc82", + "receipt": { + "to": null, + "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8", + "contractAddress": "0x4b2e688BB54DD406b6EF795064126d9A4D3d728D", + "transactionIndex": 136, + "gasUsed": "134217", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc0133b0edeb723fbb396334bd36ef120929816c24e7c61a94865c790fff13a89", + "transactionHash": "0xdbad7c40098717e179617f82fe91223795ca52a33dd605e5afed40cfafabbc82", + "logs": [], + "blockNumber": 4091624, + "cumulativeGasUsed": "25499608", + "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", + "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 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/sepolia/DummyDigest.json b/deployments/sepolia/DummyDigest.json new file mode 100644 index 00000000..147fbca9 --- /dev/null +++ b/deployments/sepolia/DummyDigest.json @@ -0,0 +1,66 @@ +{ + "address": "0x6F3e1a40BaaF32E8bd5A82EF60d7cF0490026714", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xc4321a97beea7c6de356610bc56173f146e0057eec7c64b4f475c1569e1b88ef", + "receipt": { + "to": null, + "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8", + "contractAddress": "0x6F3e1a40BaaF32E8bd5A82EF60d7cF0490026714", + "transactionIndex": 140, + "gasUsed": "123877", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9d7f5be29e41a0c9675cedc6155ab9b6506e639e781f293aac9b9345ec86737d", + "transactionHash": "0xc4321a97beea7c6de356610bc56173f146e0057eec7c64b4f475c1569e1b88ef", + "logs": [], + "blockNumber": 4091694, + "cumulativeGasUsed": "24483475", + "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\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements a dummy DNSSEC digest that approves all hashes, for testing.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/digests/DummyDigest.sol\":\"DummyDigest\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"contracts/dnssec-oracle/digests/Digest.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @dev An interface for contracts implementing a DNSSEC digest.\\n */\\ninterface Digest {\\n /**\\n * @dev Verifies a cryptographic hash.\\n * @param data The data to hash.\\n * @param hash The hash to compare to.\\n * @return True iff the hashed data matches the provided hash value.\\n */\\n function verify(\\n bytes calldata data,\\n bytes calldata hash\\n ) external pure virtual returns (bool);\\n}\\n\",\"keccak256\":\"0x8ea926b2db0578c4ad7fce4582fc0f6f0f9efee8dca2085dbdb9984f18941e28\"},\"contracts/dnssec-oracle/digests/DummyDigest.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Digest.sol\\\";\\n\\n/**\\n * @dev Implements a dummy DNSSEC digest that approves all hashes, for testing.\\n */\\ncontract DummyDigest is Digest {\\n function verify(\\n bytes calldata,\\n bytes calldata\\n ) external pure override returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x17c0c424aa79b138b918234d4d1c9b95bebad1e26e37c651628a61ef389d75e6\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610147806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f7e83aee14610030575b600080fd5b61004861003e3660046100a5565b6001949350505050565b604051901515815260200160405180910390f35b60008083601f84011261006e57600080fd5b50813567ffffffffffffffff81111561008657600080fd5b60208301915083602082850101111561009e57600080fd5b9250929050565b600080600080604085870312156100bb57600080fd5b843567ffffffffffffffff808211156100d357600080fd5b6100df8883890161005c565b909650945060208701359150808211156100f857600080fd5b506101058782880161005c565b9598949750955050505056fea2646970667358221220a959cf756a6d6f65fdf946b8ea188d413eae01a3fa027905c50b03b966d25ef764736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f7e83aee14610030575b600080fd5b61004861003e3660046100a5565b6001949350505050565b604051901515815260200160405180910390f35b60008083601f84011261006e57600080fd5b50813567ffffffffffffffff81111561008657600080fd5b60208301915083602082850101111561009e57600080fd5b9250929050565b600080600080604085870312156100bb57600080fd5b843567ffffffffffffffff808211156100d357600080fd5b6100df8883890161005c565b909650945060208701359150808211156100f857600080fd5b506101058782880161005c565b9598949750955050505056fea2646970667358221220a959cf756a6d6f65fdf946b8ea188d413eae01a3fa027905c50b03b966d25ef764736f6c63430008110033", + "devdoc": { + "details": "Implements a dummy DNSSEC digest that approves all hashes, for testing.", + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/sepolia/OffchainDNSResolver.json b/deployments/sepolia/OffchainDNSResolver.json new file mode 100644 index 00000000..ba038dc1 --- /dev/null +++ b/deployments/sepolia/OffchainDNSResolver.json @@ -0,0 +1,210 @@ +{ + "address": "0xEaDF0008EaAF803805eDb39F0d95CBdE003a2470", + "abi": [ + { + "inputs": [ + { + "internalType": "contract ENS", + "name": "_ens", + "type": "address" + }, + { + "internalType": "contract DNSSEC", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "string", + "name": "_gatewayURL", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "CouldNotResolve", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [], + "name": "ens", + "outputs": [ + { + "internalType": "contract ENS", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gatewayURL", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract DNSSEC", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x90d3718da559da9c5f5190e3b22b6df4ce40fdfb577fea053beef9a90e65b927", + "receipt": { + "to": null, + "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8", + "contractAddress": "0xEaDF0008EaAF803805eDb39F0d95CBdE003a2470", + "transactionIndex": 133, + "gasUsed": "1504295", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1a41d397a6b2c013d9382991b04c1604dad23763d1a20320bcadf13236f262dc", + "transactionHash": "0x90d3718da559da9c5f5190e3b22b6df4ce40fdfb577fea053beef9a90e65b927", + "logs": [], + "blockNumber": 4091740, + "cumulativeGasUsed": "22395149", + "status": 1, + "byzantium": true + }, + "args": [ + "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", + "0x7b3ada1c8f012bae747cf99d6cbbf70d040b84cf", + "https://dnssec-oracle.ens.domains/" + ], + "numDeployments": 1, + "solcInputHash": "e04502f562d98d0455f6c1c453418cdd", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract ENS\",\"name\":\"_ens\",\"type\":\"address\"},{\"internalType\":\"contract DNSSEC\",\"name\":\"_oracle\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_gatewayURL\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"CouldNotResolve\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ens\",\"outputs\":[{\"internalType\":\"contract ENS\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gatewayURL\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract DNSSEC\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnsregistrar/OffchainDNSResolver.sol\":\"OffchainDNSResolver\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"@ensdomains/buffer/contracts/Buffer.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-2-Clause\\npragma solidity ^0.8.4;\\n\\n/**\\n* @dev A library for working with mutable byte buffers in Solidity.\\n*\\n* Byte buffers are mutable and expandable, and provide a variety of primitives\\n* for appending to them. At any time you can fetch a bytes object containing the\\n* current contents of the buffer. The bytes object should not be stored between\\n* operations, as it may change due to resizing of the buffer.\\n*/\\nlibrary Buffer {\\n /**\\n * @dev Represents a mutable buffer. Buffers have a current value (buf) and\\n * a capacity. The capacity may be longer than the current value, in\\n * which case it can be extended without the need to allocate more memory.\\n */\\n struct buffer {\\n bytes buf;\\n uint capacity;\\n }\\n\\n /**\\n * @dev Initializes a buffer with an initial capacity.\\n * @param buf The buffer to initialize.\\n * @param capacity The number of bytes of space to allocate the buffer.\\n * @return The buffer, for chaining.\\n */\\n function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {\\n if (capacity % 32 != 0) {\\n capacity += 32 - (capacity % 32);\\n }\\n // Allocate space for the buffer data\\n buf.capacity = capacity;\\n assembly {\\n let ptr := mload(0x40)\\n mstore(buf, ptr)\\n mstore(ptr, 0)\\n let fpm := add(32, add(ptr, capacity))\\n if lt(fpm, ptr) {\\n revert(0, 0)\\n }\\n mstore(0x40, fpm)\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Initializes a new buffer from an existing bytes object.\\n * Changes to the buffer may mutate the original value.\\n * @param b The bytes object to initialize the buffer with.\\n * @return A new buffer.\\n */\\n function fromBytes(bytes memory b) internal pure returns(buffer memory) {\\n buffer memory buf;\\n buf.buf = b;\\n buf.capacity = b.length;\\n return buf;\\n }\\n\\n function resize(buffer memory buf, uint capacity) private pure {\\n bytes memory oldbuf = buf.buf;\\n init(buf, capacity);\\n append(buf, oldbuf);\\n }\\n\\n /**\\n * @dev Sets buffer length to 0.\\n * @param buf The buffer to truncate.\\n * @return The original buffer, for chaining..\\n */\\n function truncate(buffer memory buf) internal pure returns (buffer memory) {\\n assembly {\\n let bufptr := mload(buf)\\n mstore(bufptr, 0)\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to copy.\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) {\\n require(len <= data.length);\\n\\n uint off = buf.buf.length;\\n uint newCapacity = off + len;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n uint dest;\\n uint src;\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Length of existing buffer data\\n let buflen := mload(bufptr)\\n // Start address = buffer address + offset + sizeof(buffer length)\\n dest := add(add(bufptr, 32), off)\\n // Update buffer length if we're extending it\\n if gt(newCapacity, buflen) {\\n mstore(bufptr, newCapacity)\\n }\\n src := add(data, 32)\\n }\\n\\n // Copy word-length chunks while possible\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n // Copy remaining bytes\\n unchecked {\\n uint mask = (256 ** (32 - len)) - 1;\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n\\n return buf;\\n }\\n\\n /**\\n * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\\n return append(buf, data, data.length);\\n }\\n\\n /**\\n * @dev Appends a byte to the buffer. Resizes if doing so would exceed the\\n * capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint offPlusOne = off + 1;\\n if (off >= buf.capacity) {\\n resize(buf, offPlusOne * 2);\\n }\\n\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + off\\n let dest := add(add(bufptr, off), 32)\\n mstore8(dest, data)\\n // Update buffer length if we extended it\\n if gt(offPlusOne, mload(bufptr)) {\\n mstore(bufptr, offPlusOne)\\n }\\n }\\n\\n return buf;\\n }\\n\\n /**\\n * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would\\n * exceed the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to write (left-aligned).\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint newCapacity = len + off;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n unchecked {\\n uint mask = (256 ** len) - 1;\\n // Right-align data\\n data = data >> (8 * (32 - len));\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + newCapacity\\n let dest := add(bufptr, newCapacity)\\n mstore(dest, or(and(mload(dest), not(mask)), data))\\n // Update buffer length if we extended it\\n if gt(newCapacity, mload(bufptr)) {\\n mstore(bufptr, newCapacity)\\n }\\n }\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chhaining.\\n */\\n function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {\\n return append(buf, bytes32(data), 20);\\n }\\n\\n /**\\n * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {\\n return append(buf, data, 32);\\n }\\n\\n /**\\n * @dev Appends a byte to the end of the buffer. Resizes if doing so would\\n * exceed the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to write (right-aligned).\\n * @return The original buffer.\\n */\\n function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint newCapacity = len + off;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n uint mask = (256 ** len) - 1;\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + newCapacity\\n let dest := add(bufptr, newCapacity)\\n mstore(dest, or(and(mload(dest), not(mask)), data))\\n // Update buffer length if we extended it\\n if gt(newCapacity, mload(bufptr)) {\\n mstore(bufptr, newCapacity)\\n }\\n }\\n return buf;\\n }\\n}\\n\",\"keccak256\":\"0xd6dd3b0b327288f8e1b711a609f4040fea602e2ad4bba9febdf2f33b4e56eb0c\",\"license\":\"BSD-2-Clause\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/dnsregistrar/OffchainDNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../../contracts/resolvers/profiles/IAddrResolver.sol\\\";\\nimport \\\"../../contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\nimport \\\"../../contracts/resolvers/profiles/IExtendedDNSResolver.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"../dnssec-oracle/BytesUtils.sol\\\";\\nimport \\\"../dnssec-oracle/DNSSEC.sol\\\";\\nimport \\\"../dnssec-oracle/RRUtils.sol\\\";\\nimport \\\"../registry/ENSRegistry.sol\\\";\\nimport \\\"../utils/HexUtils.sol\\\";\\n\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\ninterface IDNSGateway {\\n function resolve(\\n bytes memory name,\\n uint16 qtype\\n ) external returns (DNSSEC.RRSetWithSignature[] memory);\\n}\\n\\nuint16 constant CLASS_INET = 1;\\nuint16 constant TYPE_TXT = 16;\\n\\ncontract OffchainDNSResolver is IExtendedResolver {\\n using RRUtils for *;\\n using BytesUtils for bytes;\\n using HexUtils for bytes;\\n\\n ENS public immutable ens;\\n DNSSEC public immutable oracle;\\n string public gatewayURL;\\n\\n error CouldNotResolve(bytes name);\\n\\n constructor(ENS _ens, DNSSEC _oracle, string memory _gatewayURL) {\\n ens = _ens;\\n oracle = _oracle;\\n gatewayURL = _gatewayURL;\\n }\\n\\n function resolve(\\n bytes calldata name,\\n bytes calldata data\\n ) external view returns (bytes memory) {\\n string[] memory urls = new string[](1);\\n urls[0] = gatewayURL;\\n\\n revert OffchainLookup(\\n address(this),\\n urls,\\n abi.encodeCall(IDNSGateway.resolve, (name, TYPE_TXT)),\\n OffchainDNSResolver.resolveCallback.selector,\\n abi.encode(name, data)\\n );\\n }\\n\\n function resolveCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view returns (bytes memory) {\\n (bytes memory name, bytes memory query) = abi.decode(\\n extraData,\\n (bytes, bytes)\\n );\\n DNSSEC.RRSetWithSignature[] memory rrsets = abi.decode(\\n response,\\n (DNSSEC.RRSetWithSignature[])\\n );\\n\\n (bytes memory data, ) = oracle.verifyRRSet(rrsets);\\n for (\\n RRUtils.RRIterator memory iter = data.iterateRRs(0);\\n !iter.done();\\n iter.next()\\n ) {\\n // Ignore records with wrong name, type, or class\\n bytes memory rrname = RRUtils.readName(iter.data, iter.offset);\\n if (\\n !rrname.equals(name) ||\\n iter.class != CLASS_INET ||\\n iter.dnstype != TYPE_TXT\\n ) {\\n continue;\\n }\\n\\n // Look for a valid ENS-DNS TXT record\\n (address dnsresolver, bytes memory context) = parseRR(\\n iter.data,\\n iter.rdataOffset,\\n iter.nextOffset\\n );\\n\\n // If we found a valid record, try to resolve it\\n if (dnsresolver != address(0)) {\\n if (\\n IERC165(dnsresolver).supportsInterface(\\n IExtendedDNSResolver.resolve.selector\\n )\\n ) {\\n return\\n IExtendedDNSResolver(dnsresolver).resolve(\\n name,\\n query,\\n context\\n );\\n } else if (\\n IERC165(dnsresolver).supportsInterface(\\n IExtendedResolver.resolve.selector\\n )\\n ) {\\n return IExtendedResolver(dnsresolver).resolve(name, query);\\n } else {\\n (bool ok, bytes memory ret) = address(dnsresolver)\\n .staticcall(query);\\n if (ok) {\\n return ret;\\n } else {\\n revert CouldNotResolve(name);\\n }\\n }\\n }\\n }\\n\\n // No valid records; revert.\\n revert CouldNotResolve(name);\\n }\\n\\n function parseRR(\\n bytes memory data,\\n uint256 idx,\\n uint256 lastIdx\\n ) internal view returns (address, bytes memory) {\\n bytes memory txt = readTXT(data, idx, lastIdx);\\n\\n // Must start with the magic word\\n if (txt.length < 5 || !txt.equals(0, \\\"ENS1 \\\", 0, 5)) {\\n return (address(0), \\\"\\\");\\n }\\n\\n // Parse the name or address\\n uint256 lastTxtIdx = txt.find(5, txt.length - 5, \\\" \\\");\\n if (lastTxtIdx > txt.length) {\\n address dnsResolver = parseAndResolve(txt, 5, txt.length);\\n return (dnsResolver, \\\"\\\");\\n } else {\\n address dnsResolver = parseAndResolve(txt, 5, lastTxtIdx);\\n return (\\n dnsResolver,\\n txt.substring(lastTxtIdx + 1, txt.length - lastTxtIdx - 1)\\n );\\n }\\n }\\n\\n function readTXT(\\n bytes memory data,\\n uint256 startIdx,\\n uint256 lastIdx\\n ) internal pure returns (bytes memory) {\\n // TODO: Concatenate multiple text fields\\n uint256 fieldLength = data.readUint8(startIdx);\\n assert(startIdx + fieldLength < lastIdx);\\n return data.substring(startIdx + 1, fieldLength);\\n }\\n\\n function parseAndResolve(\\n bytes memory nameOrAddress,\\n uint256 idx,\\n uint256 lastIdx\\n ) internal view returns (address) {\\n if (nameOrAddress[idx] == \\\"0\\\" && nameOrAddress[idx + 1] == \\\"x\\\") {\\n (address ret, bool valid) = nameOrAddress.hexToAddress(\\n idx + 2,\\n lastIdx\\n );\\n if (valid) {\\n return ret;\\n }\\n }\\n return resolveName(nameOrAddress, idx, lastIdx);\\n }\\n\\n function resolveName(\\n bytes memory name,\\n uint256 idx,\\n uint256 lastIdx\\n ) internal view returns (address) {\\n bytes32 node = textNamehash(name, idx, lastIdx);\\n address resolver = ens.resolver(node);\\n if (resolver == address(0)) {\\n return address(0);\\n }\\n return IAddrResolver(resolver).addr(node);\\n }\\n\\n /**\\n * @dev Namehash function that operates on dot-separated names (not dns-encoded names)\\n * @param name Name to hash\\n * @param idx Index to start at\\n * @param lastIdx Index to end at\\n */\\n function textNamehash(\\n bytes memory name,\\n uint256 idx,\\n uint256 lastIdx\\n ) internal view returns (bytes32) {\\n uint256 separator = name.find(idx, name.length - idx, bytes1(\\\".\\\"));\\n bytes32 parentNode = bytes32(0);\\n if (separator < lastIdx) {\\n parentNode = textNamehash(name, separator + 1, lastIdx);\\n } else {\\n separator = lastIdx;\\n }\\n return\\n keccak256(\\n abi.encodePacked(parentNode, name.keccak(idx, separator - idx))\\n );\\n }\\n}\\n\",\"keccak256\":\"0x2e0c9c2c85ac06b8a9a012e37e72c5b63b403c027d0cbc0ab1659ddafa26bef4\",\"license\":\"MIT\"},\"contracts/dnssec-oracle/BytesUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary BytesUtils {\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /*\\n * @dev Returns the keccak-256 hash of a byte range.\\n * @param self The byte string to hash.\\n * @param offset The position to start hashing at.\\n * @param len The number of bytes to hash.\\n * @return The hash of the byte range.\\n */\\n function keccak(\\n bytes memory self,\\n uint256 offset,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n require(offset + len <= self.length);\\n assembly {\\n ret := keccak256(add(add(self, 32), offset), len)\\n }\\n }\\n\\n /*\\n * @dev Returns a positive number if `other` comes lexicographically after\\n * `self`, a negative number if it comes before, or zero if the\\n * contents of the two bytes are equal.\\n * @param self The first bytes to compare.\\n * @param other The second bytes to compare.\\n * @return The result of the comparison.\\n */\\n function compare(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (int256) {\\n return compare(self, 0, self.length, other, 0, other.length);\\n }\\n\\n /*\\n * @dev Returns a positive number if `other` comes lexicographically after\\n * `self`, a negative number if it comes before, or zero if the\\n * contents of the two bytes are equal. Comparison is done per-rune,\\n * on unicode codepoints.\\n * @param self The first bytes to compare.\\n * @param offset The offset of self.\\n * @param len The length of self.\\n * @param other The second bytes to compare.\\n * @param otheroffset The offset of the other string.\\n * @param otherlen The length of the other string.\\n * @return The result of the comparison.\\n */\\n function compare(\\n bytes memory self,\\n uint256 offset,\\n uint256 len,\\n bytes memory other,\\n uint256 otheroffset,\\n uint256 otherlen\\n ) internal pure returns (int256) {\\n if (offset + len > self.length) {\\n revert OffsetOutOfBoundsError(offset + len, self.length);\\n }\\n if (otheroffset + otherlen > other.length) {\\n revert OffsetOutOfBoundsError(otheroffset + otherlen, other.length);\\n }\\n\\n uint256 shortest = len;\\n if (otherlen < len) shortest = otherlen;\\n\\n uint256 selfptr;\\n uint256 otherptr;\\n\\n assembly {\\n selfptr := add(self, add(offset, 32))\\n otherptr := add(other, add(otheroffset, 32))\\n }\\n for (uint256 idx = 0; idx < shortest; idx += 32) {\\n uint256 a;\\n uint256 b;\\n assembly {\\n a := mload(selfptr)\\n b := mload(otherptr)\\n }\\n if (a != b) {\\n // Mask out irrelevant bytes and check again\\n uint256 mask;\\n if (shortest - idx >= 32) {\\n mask = type(uint256).max;\\n } else {\\n mask = ~(2 ** (8 * (idx + 32 - shortest)) - 1);\\n }\\n int256 diff = int256(a & mask) - int256(b & mask);\\n if (diff != 0) return diff;\\n }\\n selfptr += 32;\\n otherptr += 32;\\n }\\n\\n return int256(len) - int256(otherlen);\\n }\\n\\n /*\\n * @dev Returns true if the two byte ranges are equal.\\n * @param self The first byte range to compare.\\n * @param offset The offset into the first byte range.\\n * @param other The second byte range to compare.\\n * @param otherOffset The offset into the second byte range.\\n * @param len The number of bytes to compare\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n uint256 offset,\\n bytes memory other,\\n uint256 otherOffset,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(self, offset, len) == keccak(other, otherOffset, len);\\n }\\n\\n /*\\n * @dev Returns true if the two byte ranges are equal with offsets.\\n * @param self The first byte range to compare.\\n * @param offset The offset into the first byte range.\\n * @param other The second byte range to compare.\\n * @param otherOffset The offset into the second byte range.\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n uint256 offset,\\n bytes memory other,\\n uint256 otherOffset\\n ) internal pure returns (bool) {\\n return\\n keccak(self, offset, self.length - offset) ==\\n keccak(other, otherOffset, other.length - otherOffset);\\n }\\n\\n /*\\n * @dev Compares a range of 'self' to all of 'other' and returns True iff\\n * they are equal.\\n * @param self The first byte range to compare.\\n * @param offset The offset into the first byte range.\\n * @param other The second byte range to compare.\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n uint256 offset,\\n bytes memory other\\n ) internal pure returns (bool) {\\n return\\n self.length == offset + other.length &&\\n equals(self, offset, other, 0, other.length);\\n }\\n\\n /*\\n * @dev Returns true if the two byte ranges are equal.\\n * @param self The first byte range to compare.\\n * @param other The second byte range to compare.\\n * @return True if the byte ranges are equal, false otherwise.\\n */\\n function equals(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (bool) {\\n return\\n self.length == other.length &&\\n equals(self, 0, other, 0, self.length);\\n }\\n\\n /*\\n * @dev Returns the 8-bit number at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 8 bits of the string, interpreted as an integer.\\n */\\n function readUint8(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (uint8 ret) {\\n return uint8(self[idx]);\\n }\\n\\n /*\\n * @dev Returns the 16-bit number at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 16 bits of the string, interpreted as an integer.\\n */\\n function readUint16(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (uint16 ret) {\\n require(idx + 2 <= self.length);\\n assembly {\\n ret := and(mload(add(add(self, 2), idx)), 0xFFFF)\\n }\\n }\\n\\n /*\\n * @dev Returns the 32-bit number at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 32 bits of the string, interpreted as an integer.\\n */\\n function readUint32(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (uint32 ret) {\\n require(idx + 4 <= self.length);\\n assembly {\\n ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF)\\n }\\n }\\n\\n /*\\n * @dev Returns the 32 byte value at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 32 bytes of the string.\\n */\\n function readBytes32(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (bytes32 ret) {\\n require(idx + 32 <= self.length);\\n assembly {\\n ret := mload(add(add(self, 32), idx))\\n }\\n }\\n\\n /*\\n * @dev Returns the 32 byte value at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes\\n * @return The specified 32 bytes of the string.\\n */\\n function readBytes20(\\n bytes memory self,\\n uint256 idx\\n ) internal pure returns (bytes20 ret) {\\n require(idx + 20 <= self.length);\\n assembly {\\n ret := and(\\n mload(add(add(self, 32), idx)),\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000\\n )\\n }\\n }\\n\\n /*\\n * @dev Returns the n byte value at the specified index of self.\\n * @param self The byte string.\\n * @param idx The index into the bytes.\\n * @param len The number of bytes.\\n * @return The specified 32 bytes of the string.\\n */\\n function readBytesN(\\n bytes memory self,\\n uint256 idx,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n require(len <= 32);\\n require(idx + len <= self.length);\\n assembly {\\n let mask := not(sub(exp(256, sub(32, len)), 1))\\n ret := and(mload(add(add(self, 32), idx)), mask)\\n }\\n }\\n\\n function memcpy(uint256 dest, uint256 src, uint256 len) private pure {\\n // Copy word-length chunks while possible\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n // Copy remaining bytes\\n unchecked {\\n uint256 mask = (256 ** (32 - len)) - 1;\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n }\\n\\n /*\\n * @dev Copies a substring into a new byte string.\\n * @param self The byte string to copy from.\\n * @param offset The offset to start copying at.\\n * @param len The number of bytes to copy.\\n */\\n function substring(\\n bytes memory self,\\n uint256 offset,\\n uint256 len\\n ) internal pure returns (bytes memory) {\\n require(offset + len <= self.length);\\n\\n bytes memory ret = new bytes(len);\\n uint256 dest;\\n uint256 src;\\n\\n assembly {\\n dest := add(ret, 32)\\n src := add(add(self, 32), offset)\\n }\\n memcpy(dest, src, len);\\n\\n return ret;\\n }\\n\\n // Maps characters from 0x30 to 0x7A to their base32 values.\\n // 0xFF represents invalid characters in that range.\\n bytes constant base32HexTable =\\n hex\\\"00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\\\";\\n\\n /**\\n * @dev Decodes unpadded base32 data of up to one word in length.\\n * @param self The data to decode.\\n * @param off Offset into the string to start at.\\n * @param len Number of characters to decode.\\n * @return The decoded data, left aligned.\\n */\\n function base32HexDecodeWord(\\n bytes memory self,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32) {\\n require(len <= 52);\\n\\n uint256 ret = 0;\\n uint8 decoded;\\n for (uint256 i = 0; i < len; i++) {\\n bytes1 char = self[off + i];\\n require(char >= 0x30 && char <= 0x7A);\\n decoded = uint8(base32HexTable[uint256(uint8(char)) - 0x30]);\\n require(decoded <= 0x20);\\n if (i == len - 1) {\\n break;\\n }\\n ret = (ret << 5) | decoded;\\n }\\n\\n uint256 bitlen = len * 5;\\n if (len % 8 == 0) {\\n // Multiple of 8 characters, no padding\\n ret = (ret << 5) | decoded;\\n } else if (len % 8 == 2) {\\n // Two extra characters - 1 byte\\n ret = (ret << 3) | (decoded >> 2);\\n bitlen -= 2;\\n } else if (len % 8 == 4) {\\n // Four extra characters - 2 bytes\\n ret = (ret << 1) | (decoded >> 4);\\n bitlen -= 4;\\n } else if (len % 8 == 5) {\\n // Five extra characters - 3 bytes\\n ret = (ret << 4) | (decoded >> 1);\\n bitlen -= 1;\\n } else if (len % 8 == 7) {\\n // Seven extra characters - 4 bytes\\n ret = (ret << 2) | (decoded >> 3);\\n bitlen -= 3;\\n } else {\\n revert();\\n }\\n\\n return bytes32(ret << (256 - bitlen));\\n }\\n\\n /**\\n * @dev Finds the first occurrence of the byte `needle` in `self`.\\n * @param self The string to search\\n * @param off The offset to start searching at\\n * @param len The number of bytes to search\\n * @param needle The byte to search for\\n * @return The offset of `needle` in `self`, or 2**256-1 if it was not found.\\n */\\n function find(\\n bytes memory self,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 idx = off; idx < off + len; idx++) {\\n if (self[idx] == needle) {\\n return idx;\\n }\\n }\\n return type(uint256).max;\\n }\\n}\\n\",\"keccak256\":\"0x4f10902639b85a17ae10745264feff322e793bfb1bc130a9a90efa7dda47c6cc\"},\"contracts/dnssec-oracle/DNSSEC.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\npragma experimental ABIEncoderV2;\\n\\nabstract contract DNSSEC {\\n bytes public anchors;\\n\\n struct RRSetWithSignature {\\n bytes rrset;\\n bytes sig;\\n }\\n\\n event AlgorithmUpdated(uint8 id, address addr);\\n event DigestUpdated(uint8 id, address addr);\\n\\n function verifyRRSet(\\n RRSetWithSignature[] memory input\\n ) external view virtual returns (bytes memory rrs, uint32 inception);\\n\\n function verifyRRSet(\\n RRSetWithSignature[] memory input,\\n uint256 now\\n ) public view virtual returns (bytes memory rrs, uint32 inception);\\n}\\n\",\"keccak256\":\"0xee6a236a59e5db8418c98ee4640a91987d26533c02d305cc6c7a37a3ac4ee907\",\"license\":\"MIT\"},\"contracts/dnssec-oracle/RRUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./BytesUtils.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\n/**\\n * @dev RRUtils is a library that provides utilities for parsing DNS resource records.\\n */\\nlibrary RRUtils {\\n using BytesUtils for *;\\n using Buffer for *;\\n\\n /**\\n * @dev Returns the number of bytes in the DNS name at 'offset' in 'self'.\\n * @param self The byte array to read a name from.\\n * @param offset The offset to start reading at.\\n * @return The length of the DNS name at 'offset', in bytes.\\n */\\n function nameLength(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (uint256) {\\n uint256 idx = offset;\\n while (true) {\\n assert(idx < self.length);\\n uint256 labelLen = self.readUint8(idx);\\n idx += labelLen + 1;\\n if (labelLen == 0) {\\n break;\\n }\\n }\\n return idx - offset;\\n }\\n\\n /**\\n * @dev Returns a DNS format name at the specified offset of self.\\n * @param self The byte array to read a name from.\\n * @param offset The offset to start reading at.\\n * @return ret The name.\\n */\\n function readName(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (bytes memory ret) {\\n uint256 len = nameLength(self, offset);\\n return self.substring(offset, len);\\n }\\n\\n /**\\n * @dev Returns the number of labels in the DNS name at 'offset' in 'self'.\\n * @param self The byte array to read a name from.\\n * @param offset The offset to start reading at.\\n * @return The number of labels in the DNS name at 'offset', in bytes.\\n */\\n function labelCount(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (uint256) {\\n uint256 count = 0;\\n while (true) {\\n assert(offset < self.length);\\n uint256 labelLen = self.readUint8(offset);\\n offset += labelLen + 1;\\n if (labelLen == 0) {\\n break;\\n }\\n count += 1;\\n }\\n return count;\\n }\\n\\n uint256 constant RRSIG_TYPE = 0;\\n uint256 constant RRSIG_ALGORITHM = 2;\\n uint256 constant RRSIG_LABELS = 3;\\n uint256 constant RRSIG_TTL = 4;\\n uint256 constant RRSIG_EXPIRATION = 8;\\n uint256 constant RRSIG_INCEPTION = 12;\\n uint256 constant RRSIG_KEY_TAG = 16;\\n uint256 constant RRSIG_SIGNER_NAME = 18;\\n\\n struct SignedSet {\\n uint16 typeCovered;\\n uint8 algorithm;\\n uint8 labels;\\n uint32 ttl;\\n uint32 expiration;\\n uint32 inception;\\n uint16 keytag;\\n bytes signerName;\\n bytes data;\\n bytes name;\\n }\\n\\n function readSignedSet(\\n bytes memory data\\n ) internal pure returns (SignedSet memory self) {\\n self.typeCovered = data.readUint16(RRSIG_TYPE);\\n self.algorithm = data.readUint8(RRSIG_ALGORITHM);\\n self.labels = data.readUint8(RRSIG_LABELS);\\n self.ttl = data.readUint32(RRSIG_TTL);\\n self.expiration = data.readUint32(RRSIG_EXPIRATION);\\n self.inception = data.readUint32(RRSIG_INCEPTION);\\n self.keytag = data.readUint16(RRSIG_KEY_TAG);\\n self.signerName = readName(data, RRSIG_SIGNER_NAME);\\n self.data = data.substring(\\n RRSIG_SIGNER_NAME + self.signerName.length,\\n data.length - RRSIG_SIGNER_NAME - self.signerName.length\\n );\\n }\\n\\n function rrs(\\n SignedSet memory rrset\\n ) internal pure returns (RRIterator memory) {\\n return iterateRRs(rrset.data, 0);\\n }\\n\\n /**\\n * @dev An iterator over resource records.\\n */\\n struct RRIterator {\\n bytes data;\\n uint256 offset;\\n uint16 dnstype;\\n uint16 class;\\n uint32 ttl;\\n uint256 rdataOffset;\\n uint256 nextOffset;\\n }\\n\\n /**\\n * @dev Begins iterating over resource records.\\n * @param self The byte string to read from.\\n * @param offset The offset to start reading at.\\n * @return ret An iterator object.\\n */\\n function iterateRRs(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (RRIterator memory ret) {\\n ret.data = self;\\n ret.nextOffset = offset;\\n next(ret);\\n }\\n\\n /**\\n * @dev Returns true iff there are more RRs to iterate.\\n * @param iter The iterator to check.\\n * @return True iff the iterator has finished.\\n */\\n function done(RRIterator memory iter) internal pure returns (bool) {\\n return iter.offset >= iter.data.length;\\n }\\n\\n /**\\n * @dev Moves the iterator to the next resource record.\\n * @param iter The iterator to advance.\\n */\\n function next(RRIterator memory iter) internal pure {\\n iter.offset = iter.nextOffset;\\n if (iter.offset >= iter.data.length) {\\n return;\\n }\\n\\n // Skip the name\\n uint256 off = iter.offset + nameLength(iter.data, iter.offset);\\n\\n // Read type, class, and ttl\\n iter.dnstype = iter.data.readUint16(off);\\n off += 2;\\n iter.class = iter.data.readUint16(off);\\n off += 2;\\n iter.ttl = iter.data.readUint32(off);\\n off += 4;\\n\\n // Read the rdata\\n uint256 rdataLength = iter.data.readUint16(off);\\n off += 2;\\n iter.rdataOffset = off;\\n iter.nextOffset = off + rdataLength;\\n }\\n\\n /**\\n * @dev Returns the name of the current record.\\n * @param iter The iterator.\\n * @return A new bytes object containing the owner name from the RR.\\n */\\n function name(RRIterator memory iter) internal pure returns (bytes memory) {\\n return\\n iter.data.substring(\\n iter.offset,\\n nameLength(iter.data, iter.offset)\\n );\\n }\\n\\n /**\\n * @dev Returns the rdata portion of the current record.\\n * @param iter The iterator.\\n * @return A new bytes object containing the RR's RDATA.\\n */\\n function rdata(\\n RRIterator memory iter\\n ) internal pure returns (bytes memory) {\\n return\\n iter.data.substring(\\n iter.rdataOffset,\\n iter.nextOffset - iter.rdataOffset\\n );\\n }\\n\\n uint256 constant DNSKEY_FLAGS = 0;\\n uint256 constant DNSKEY_PROTOCOL = 2;\\n uint256 constant DNSKEY_ALGORITHM = 3;\\n uint256 constant DNSKEY_PUBKEY = 4;\\n\\n struct DNSKEY {\\n uint16 flags;\\n uint8 protocol;\\n uint8 algorithm;\\n bytes publicKey;\\n }\\n\\n function readDNSKEY(\\n bytes memory data,\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (DNSKEY memory self) {\\n self.flags = data.readUint16(offset + DNSKEY_FLAGS);\\n self.protocol = data.readUint8(offset + DNSKEY_PROTOCOL);\\n self.algorithm = data.readUint8(offset + DNSKEY_ALGORITHM);\\n self.publicKey = data.substring(\\n offset + DNSKEY_PUBKEY,\\n length - DNSKEY_PUBKEY\\n );\\n }\\n\\n uint256 constant DS_KEY_TAG = 0;\\n uint256 constant DS_ALGORITHM = 2;\\n uint256 constant DS_DIGEST_TYPE = 3;\\n uint256 constant DS_DIGEST = 4;\\n\\n struct DS {\\n uint16 keytag;\\n uint8 algorithm;\\n uint8 digestType;\\n bytes digest;\\n }\\n\\n function readDS(\\n bytes memory data,\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (DS memory self) {\\n self.keytag = data.readUint16(offset + DS_KEY_TAG);\\n self.algorithm = data.readUint8(offset + DS_ALGORITHM);\\n self.digestType = data.readUint8(offset + DS_DIGEST_TYPE);\\n self.digest = data.substring(offset + DS_DIGEST, length - DS_DIGEST);\\n }\\n\\n function isSubdomainOf(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (bool) {\\n uint256 off = 0;\\n uint256 counts = labelCount(self, 0);\\n uint256 othercounts = labelCount(other, 0);\\n\\n while (counts > othercounts) {\\n off = progress(self, off);\\n counts--;\\n }\\n\\n return self.equals(off, other, 0);\\n }\\n\\n function compareNames(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (int256) {\\n if (self.equals(other)) {\\n return 0;\\n }\\n\\n uint256 off;\\n uint256 otheroff;\\n uint256 prevoff;\\n uint256 otherprevoff;\\n uint256 counts = labelCount(self, 0);\\n uint256 othercounts = labelCount(other, 0);\\n\\n // Keep removing labels from the front of the name until both names are equal length\\n while (counts > othercounts) {\\n prevoff = off;\\n off = progress(self, off);\\n counts--;\\n }\\n\\n while (othercounts > counts) {\\n otherprevoff = otheroff;\\n otheroff = progress(other, otheroff);\\n othercounts--;\\n }\\n\\n // Compare the last nonequal labels to each other\\n while (counts > 0 && !self.equals(off, other, otheroff)) {\\n prevoff = off;\\n off = progress(self, off);\\n otherprevoff = otheroff;\\n otheroff = progress(other, otheroff);\\n counts -= 1;\\n }\\n\\n if (off == 0) {\\n return -1;\\n }\\n if (otheroff == 0) {\\n return 1;\\n }\\n\\n return\\n self.compare(\\n prevoff + 1,\\n self.readUint8(prevoff),\\n other,\\n otherprevoff + 1,\\n other.readUint8(otherprevoff)\\n );\\n }\\n\\n /**\\n * @dev Compares two serial numbers using RFC1982 serial number math.\\n */\\n function serialNumberGte(\\n uint32 i1,\\n uint32 i2\\n ) internal pure returns (bool) {\\n unchecked {\\n return int32(i1) - int32(i2) >= 0;\\n }\\n }\\n\\n function progress(\\n bytes memory body,\\n uint256 off\\n ) internal pure returns (uint256) {\\n return off + 1 + body.readUint8(off);\\n }\\n\\n /**\\n * @dev Computes the keytag for a chunk of data.\\n * @param data The data to compute a keytag for.\\n * @return The computed key tag.\\n */\\n function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n /* This function probably deserves some explanation.\\n * The DNSSEC keytag function is a checksum that relies on summing up individual bytes\\n * from the input string, with some mild bitshifting. Here's a Naive solidity implementation:\\n *\\n * function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n * uint ac;\\n * for (uint i = 0; i < data.length; i++) {\\n * ac += i & 1 == 0 ? uint16(data.readUint8(i)) << 8 : data.readUint8(i);\\n * }\\n * return uint16(ac + (ac >> 16));\\n * }\\n *\\n * The EVM, with its 256 bit words, is exceedingly inefficient at doing byte-by-byte operations;\\n * the code above, on reasonable length inputs, consumes over 100k gas. But we can make the EVM's\\n * large words work in our favour.\\n *\\n * The code below works by treating the input as a series of 256 bit words. It first masks out\\n * even and odd bytes from each input word, adding them to two separate accumulators `ac1` and `ac2`.\\n * The bytes are separated by empty bytes, so as long as no individual sum exceeds 2^16-1, we're\\n * effectively summing 16 different numbers with each EVM ADD opcode.\\n *\\n * Once it's added up all the inputs, it has to add all the 16 bit values in `ac1` and `ac2` together.\\n * It does this using the same trick - mask out every other value, shift to align them, add them together.\\n * After the first addition on both accumulators, there's enough room to add the two accumulators together,\\n * and the remaining sums can be done just on ac1.\\n */\\n unchecked {\\n require(data.length <= 8192, \\\"Long keys not permitted\\\");\\n uint256 ac1;\\n uint256 ac2;\\n for (uint256 i = 0; i < data.length + 31; i += 32) {\\n uint256 word;\\n assembly {\\n word := mload(add(add(data, 32), i))\\n }\\n if (i + 32 > data.length) {\\n uint256 unused = 256 - (data.length - i) * 8;\\n word = (word >> unused) << unused;\\n }\\n ac1 +=\\n (word &\\n 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >>\\n 8;\\n ac2 += (word &\\n 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF);\\n }\\n ac1 =\\n (ac1 &\\n 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n ((ac1 &\\n 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n 16);\\n ac2 =\\n (ac2 &\\n 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n ((ac2 &\\n 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n 16);\\n ac1 = (ac1 << 8) + ac2;\\n ac1 =\\n (ac1 &\\n 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) +\\n ((ac1 &\\n 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >>\\n 32);\\n ac1 =\\n (ac1 &\\n 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) +\\n ((ac1 &\\n 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >>\\n 64);\\n ac1 =\\n (ac1 &\\n 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +\\n (ac1 >> 128);\\n ac1 += (ac1 >> 16) & 0xFFFF;\\n return uint16(ac1);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x4dd68a6efd7c38f6b0e95ca0c056ecb74f88583da650b1a8639e6e78be36fede\"},\"contracts/registry/ENS.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x7cb1158c7d268b63de1468e28e2711b28d686e2628ddb22da2149cd93ddeafda\"},\"contracts/registry/ENSRegistry.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\nimport \\\"./ENS.sol\\\";\\n\\n/**\\n * The ENS registry contract.\\n */\\ncontract ENSRegistry is ENS {\\n struct Record {\\n address owner;\\n address resolver;\\n uint64 ttl;\\n }\\n\\n mapping(bytes32 => Record) records;\\n mapping(address => mapping(address => bool)) operators;\\n\\n // Permits modifications only by the owner of the specified node.\\n modifier authorised(bytes32 node) {\\n address owner = records[node].owner;\\n require(owner == msg.sender || operators[owner][msg.sender]);\\n _;\\n }\\n\\n /**\\n * @dev Constructs a new ENS registry.\\n */\\n constructor() public {\\n records[0x0].owner = msg.sender;\\n }\\n\\n /**\\n * @dev Sets the record for a node.\\n * @param node The node to update.\\n * @param owner The address of the new owner.\\n * @param resolver The address of the resolver.\\n * @param ttl The TTL in seconds.\\n */\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external virtual override {\\n setOwner(node, owner);\\n _setResolverAndTTL(node, resolver, ttl);\\n }\\n\\n /**\\n * @dev Sets the record for a subnode.\\n * @param node The parent node.\\n * @param label The hash of the label specifying the subnode.\\n * @param owner The address of the new owner.\\n * @param resolver The address of the resolver.\\n * @param ttl The TTL in seconds.\\n */\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external virtual override {\\n bytes32 subnode = setSubnodeOwner(node, label, owner);\\n _setResolverAndTTL(subnode, resolver, ttl);\\n }\\n\\n /**\\n * @dev Transfers ownership of a node to a new address. May only be called by the current owner of the node.\\n * @param node The node to transfer ownership of.\\n * @param owner The address of the new owner.\\n */\\n function setOwner(\\n bytes32 node,\\n address owner\\n ) public virtual override authorised(node) {\\n _setOwner(node, owner);\\n emit Transfer(node, owner);\\n }\\n\\n /**\\n * @dev Transfers ownership of a subnode keccak256(node, label) to a new address. May only be called by the owner of the parent node.\\n * @param node The parent node.\\n * @param label The hash of the label specifying the subnode.\\n * @param owner The address of the new owner.\\n */\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) public virtual override authorised(node) returns (bytes32) {\\n bytes32 subnode = keccak256(abi.encodePacked(node, label));\\n _setOwner(subnode, owner);\\n emit NewOwner(node, label, owner);\\n return subnode;\\n }\\n\\n /**\\n * @dev Sets the resolver address for the specified node.\\n * @param node The node to update.\\n * @param resolver The address of the resolver.\\n */\\n function setResolver(\\n bytes32 node,\\n address resolver\\n ) public virtual override authorised(node) {\\n emit NewResolver(node, resolver);\\n records[node].resolver = resolver;\\n }\\n\\n /**\\n * @dev Sets the TTL for the specified node.\\n * @param node The node to update.\\n * @param ttl The TTL in seconds.\\n */\\n function setTTL(\\n bytes32 node,\\n uint64 ttl\\n ) public virtual override authorised(node) {\\n emit NewTTL(node, ttl);\\n records[node].ttl = ttl;\\n }\\n\\n /**\\n * @dev Enable or disable approval for a third party (\\\"operator\\\") to manage\\n * all of `msg.sender`'s ENS records. Emits the ApprovalForAll event.\\n * @param operator Address to add to the set of authorized operators.\\n * @param approved True if the operator is approved, false to revoke approval.\\n */\\n function setApprovalForAll(\\n address operator,\\n bool approved\\n ) external virtual override {\\n operators[msg.sender][operator] = approved;\\n emit ApprovalForAll(msg.sender, operator, approved);\\n }\\n\\n /**\\n * @dev Returns the address that owns the specified node.\\n * @param node The specified node.\\n * @return address of the owner.\\n */\\n function owner(\\n bytes32 node\\n ) public view virtual override returns (address) {\\n address addr = records[node].owner;\\n if (addr == address(this)) {\\n return address(0x0);\\n }\\n\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address of the resolver for the specified node.\\n * @param node The specified node.\\n * @return address of the resolver.\\n */\\n function resolver(\\n bytes32 node\\n ) public view virtual override returns (address) {\\n return records[node].resolver;\\n }\\n\\n /**\\n * @dev Returns the TTL of a node, and any records associated with it.\\n * @param node The specified node.\\n * @return ttl of the node.\\n */\\n function ttl(bytes32 node) public view virtual override returns (uint64) {\\n return records[node].ttl;\\n }\\n\\n /**\\n * @dev Returns whether a record has been imported to the registry.\\n * @param node The specified node.\\n * @return Bool if record exists\\n */\\n function recordExists(\\n bytes32 node\\n ) public view virtual override returns (bool) {\\n return records[node].owner != address(0x0);\\n }\\n\\n /**\\n * @dev Query if an address is an authorized operator for another address.\\n * @param owner The address that owns the records.\\n * @param operator The address that acts on behalf of the owner.\\n * @return True if `operator` is an approved operator for `owner`, false otherwise.\\n */\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view virtual override returns (bool) {\\n return operators[owner][operator];\\n }\\n\\n function _setOwner(bytes32 node, address owner) internal virtual {\\n records[node].owner = owner;\\n }\\n\\n function _setResolverAndTTL(\\n bytes32 node,\\n address resolver,\\n uint64 ttl\\n ) internal {\\n if (resolver != records[node].resolver) {\\n records[node].resolver = resolver;\\n emit NewResolver(node, resolver);\\n }\\n\\n if (ttl != records[node].ttl) {\\n records[node].ttl = ttl;\\n emit NewTTL(node, ttl);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa7a7a64fb980e521c991415e416fd4106a42f892479805e1daa51ecb0e2e5198\"},\"contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/**\\n * Interface for the legacy (ETH-only) addr function.\\n */\\ninterface IAddrResolver {\\n event AddrChanged(bytes32 indexed node, address a);\\n\\n /**\\n * Returns the address associated with an ENS node.\\n * @param node The ENS node to query.\\n * @return The associated address.\\n */\\n function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x2ad7f2fc60ebe0f93745fe70247f6a854f66af732483fda2a3c5e055614445e8\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IExtendedDNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedDNSResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data,\\n bytes memory context\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x541f8799c34ff9e7035d09f06ae0f0f8a16b6065e9b60a15670b957321630f72\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /**\\n * @dev Attempts to parse bytes32 from a hex string\\n * @param str The string to parse\\n * @param idx The offset to start parsing at\\n * @param lastIdx The (exclusive) last index in `str` to consider. Use `str.length` to scan the whole string.\\n */\\n function hexStringToBytes32(\\n bytes memory str,\\n uint256 idx,\\n uint256 lastIdx\\n ) internal pure returns (bytes32 r, bool valid) {\\n valid = true;\\n assembly {\\n // check that the index to read to is not past the end of the string\\n if gt(lastIdx, mload(str)) {\\n revert(0, 0)\\n }\\n\\n function getHex(c) -> ascii {\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0xff\\n }\\n\\n let ptr := add(str, 32)\\n for {\\n let i := idx\\n } lt(i, lastIdx) {\\n i := add(i, 2)\\n } {\\n let byte1 := getHex(byte(0, mload(add(ptr, i))))\\n let byte2 := getHex(byte(0, mload(add(ptr, add(i, 1)))))\\n // if either byte is invalid, set invalid and break loop\\n if or(eq(byte1, 0xff), eq(byte2, 0xff)) {\\n valid := false\\n break\\n }\\n let combined := or(shl(4, byte1), byte2)\\n r := or(shl(8, r), combined)\\n }\\n }\\n }\\n\\n /**\\n * @dev Attempts to parse an address from a hex string\\n * @param str The string to parse\\n * @param idx The offset to start parsing at\\n * @param lastIdx The (exclusive) last index in `str` to consider. Use `str.length` to scan the whole string.\\n */\\n function hexToAddress(\\n bytes memory str,\\n uint256 idx,\\n uint256 lastIdx\\n ) internal pure returns (address, bool) {\\n if (lastIdx - idx < 40) return (address(0x0), false);\\n (bytes32 r, bool valid) = hexStringToBytes32(str, idx, lastIdx);\\n return (address(uint160(uint256(r))), valid);\\n }\\n}\\n\",\"keccak256\":\"0xcae20ad72181f47dfe7fba7d88e8d902a01576b16e93362878e726989d6cfb4d\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b5060405162001c0238038062001c0283398101604081905262000034916200008e565b6001600160a01b03808416608052821660a05260006200005582826200021d565b50505050620002e9565b6001600160a01b03811681146200007557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b600080600060608486031215620000a457600080fd5b8351620000b1816200005f565b80935050602080850151620000c6816200005f565b60408601519093506001600160401b0380821115620000e457600080fd5b818701915087601f830112620000f957600080fd5b8151818111156200010e576200010e62000078565b604051601f8201601f19908116603f0116810190838211818310171562000139576200013962000078565b816040528281528a868487010111156200015257600080fd5b600093505b8284101562000176578484018601518185018701529285019262000157565b60008684830101528096505050505050509250925092565b600181811c90821680620001a357607f821691505b602082108103620001c457634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200021857600081815260208120601f850160051c81016020861015620001f35750805b601f850160051c820191505b818110156200021457828155600101620001ff565b5050505b505050565b81516001600160401b0381111562000239576200023962000078565b62000251816200024a84546200018e565b84620001ca565b602080601f831160018114620002895760008415620002705750858301515b600019600386901b1c1916600185901b17855562000214565b600085815260208120601f198616915b82811015620002ba5788860151825594840194600190910190840162000299565b5085821015620002d95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a0516118e76200031b6000396000818160ca015261039901526000818160710152610e7001526118e76000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637dc0d1d0116100505780637dc0d1d0146100c55780639061b923146100ec578063b4a85801146100ff57600080fd5b80633f15457f1461006c57806352539968146100b0575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100b8610112565b6040516100a7919061114c565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100b86100fa3660046111a8565b6101a0565b6100b861010d3660046111a8565b61036f565b6000805461011f90611214565b80601f016020809104026020016040519081016040528092919081815260200182805461014b90611214565b80156101985780601f1061016d57610100808354040283529160200191610198565b820191906000526020600020905b81548152906001019060200180831161017b57829003601f168201915b505050505081565b60408051600180825281830190925260609160009190816020015b60608152602001906001900390816101bb579050509050600080546101df90611214565b80601f016020809104026020016040519081016040528092919081815260200182805461020b90611214565b80156102585780601f1061022d57610100808354040283529160200191610258565b820191906000526020600020905b81548152906001019060200180831161023b57829003601f168201915b50505050508160008151811061027057610270611264565b6020026020010181905250308187876010604051602401610293939291906112a3565b60408051601f19818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f31b137b90000000000000000000000000000000000000000000000000000000017905290517fb4a858010000000000000000000000000000000000000000000000000000000091610322918c918c918c918c91016112cb565b60408051601f19818403018152908290527f556f183000000000000000000000000000000000000000000000000000000000825261036695949392916004016112fd565b60405180910390fd5b606060008061038084860186611499565b90925090506000610393878901896114fd565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bdf95fef836040518263ffffffff1660e01b81526004016103e3919061161b565b600060405180830381865afa158015610400573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261042891908101906116e5565b5090506000610437828261072c565b90505b8051516020820151101561070857600061045c82600001518360200151610793565b905061046881876107ae565b158061047d5750606082015161ffff16600114155b806104915750604082015161ffff16601014155b1561049c57506106fa565b6000806104b684600001518560a001518660c001516107d3565b90925090506001600160a01b038216156106f6576040516301ffc9a760e01b815263477cc53f60e11b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa158015610515573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105399190611740565b156105c25760405163477cc53f60e11b81526001600160a01b03831690638ef98a7e9061056e908b908b908690600401611762565b600060405180830381865afa15801561058b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105b3919081019061179b565b98505050505050505050610724565b6040516301ffc9a760e01b8152639061b92360e01b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa15801561060d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106319190611740565b1561066457604051639061b92360e01b81526001600160a01b03831690639061b9239061056e908b908b906004016117d0565b600080836001600160a01b03168960405161067f91906117f5565b600060405180830381855afa9150503d80600081146106ba576040519150601f19603f3d011682016040523d82523d6000602084013e6106bf565b606091505b509150915081156106db57995061072498505050505050505050565b896040516314d3b60360e11b8152600401610366919061114c565b5050505b61070381610922565b61043a565b50836040516314d3b60360e11b8152600401610366919061114c565b949350505050565b61077a6040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261078d81610922565b92915050565b606060006107a18484610a0a565b9050610724848483610a64565b6000815183511480156107cc57506107cc8360008460008751610ae6565b9392505050565b6000606060006107e4868686610b09565b905060058151108061083957506040805180820190915260058082527f454e5331200000000000000000000000000000000000000000000000000000006020830152610837918391600091908290610ae6565b155b1561085757505060408051602081019091526000808252915061091a565b6000610894600580845161086b9190611827565b8491907f2000000000000000000000000000000000000000000000000000000000000000610b53565b905081518111156108cb5760006108ae8360058551610bef565b604080516020810190915260008152909550935061091a92505050565b60006108d983600584610bef565b90508061090b6108ea84600161183a565b60018587516108f99190611827565b6109039190611827565b869190610a64565b9450945050505061091a565b50505b935093915050565b60c081015160208201819052815151116109395750565b600061094d82600001518360200151610a0a565b826020015161095c919061183a565b825190915061096b9082610cf9565b61ffff16604083015261097f60028261183a565b825190915061098e9082610cf9565b61ffff1660608301526109a260028261183a565b82519091506109b19082610d21565b63ffffffff1660808301526109c760048261183a565b82519091506000906109d99083610cf9565b61ffff1690506109ea60028361183a565b60a0840181905291506109fd818361183a565b60c0909301929092525050565b6000815b83518110610a1e57610a1e61184d565b6000610a2a8583610d4b565b60ff169050610a3a81600161183a565b610a44908361183a565b915080600003610a545750610a5a565b50610a0e565b6107248382611827565b8251606090610a73838561183a565b1115610a7e57600080fd5b60008267ffffffffffffffff811115610a9957610a9961124e565b6040519080825280601f01601f191660200182016040528015610ac3576020820181803683370190505b50905060208082019086860101610adb828287610d6f565b509095945050505050565b6000610af3848484610dc5565b610afe878785610dc5565b149695505050505050565b60606000610b178585610d4b565b60ff16905082610b27828661183a565b10610b3457610b3461184d565b610b4a610b4285600161183a565b869083610a64565b95945050505050565b6000835b610b61848661183a565b811015610be257827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916868281518110610b9d57610b9d611264565b01602001517fff000000000000000000000000000000000000000000000000000000000000001603610bd0579050610724565b80610bda81611863565b915050610b57565b5060001995945050505050565b6000838381518110610c0357610c03611264565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f3000000000000000000000000000000000000000000000000000000000000000148015610cbb575083610c6084600161183a565b81518110610c7057610c70611264565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f7800000000000000000000000000000000000000000000000000000000000000145b15610cee57600080610cd9610cd186600261183a565b879086610de9565b915091508015610ceb575090506107cc565b50505b610724848484610e25565b8151600090610d0983600261183a565b1115610d1457600080fd5b50016002015161ffff1690565b8151600090610d3183600461183a565b1115610d3c57600080fd5b50016004015163ffffffff1690565b6000828281518110610d5f57610d5f611264565b016020015160f81c905092915050565b60208110610da75781518352610d8660208461183a565b9250610d9360208361183a565b9150610da0602082611827565b9050610d6f565b905182516020929092036101000a6000190180199091169116179052565b8251600090610dd4838561183a565b1115610ddf57600080fd5b5091016020012090565b6000806028610df88585611827565b1015610e095750600090508061091a565b600080610e17878787610f82565b909890975095505050505050565b600080610e33858585611049565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018290529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630178b8bf90602401602060405180830381865afa158015610eb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edb9190611894565b90506001600160a01b038116610ef6576000925050506107cc565b6040517f3b3b57de000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b03821690633b3b57de90602401602060405180830381865afa158015610f54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f789190611894565b9695505050505050565b8251600090600190831115610f9657600080fd5b610fe7565b6000603a8210602f83111615610fb35750602f190190565b60478210604083111615610fc957506036190190565b60678210606083111615610fdf57506056190190565b5060ff919050565b60208501845b84811015610917576110048183015160001a610f9b565b6110166001830184015160001a610f9b565b60ff811460ff8314171561102f57600094505050610917565b60049190911b1760089490941b9390931792600201610fed565b6000806110868485875161105d9190611827565b8791907f2e00000000000000000000000000000000000000000000000000000000000000610b53565b90506000838210156110ae576110a7866110a184600161183a565b86611049565b90506110b2565b8391505b806110c9866110c18186611827565b899190610dc5565b60408051602081019390935282015260600160405160208183030381529060405280519060200120925050509392505050565b60005b838110156111175781810151838201526020016110ff565b50506000910152565b600081518084526111388160208601602086016110fc565b601f01601f19169290920160200192915050565b6020815260006107cc6020830184611120565b60008083601f84011261117157600080fd5b50813567ffffffffffffffff81111561118957600080fd5b6020830191508360208285010111156111a157600080fd5b9250929050565b600080600080604085870312156111be57600080fd5b843567ffffffffffffffff808211156111d657600080fd5b6111e28883890161115f565b909650945060208701359150808211156111fb57600080fd5b506112088782880161115f565b95989497509550505050565b600181811c9082168061122857607f821691505b60208210810361124857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6040815260006112b760408301858761127a565b905061ffff83166020830152949350505050565b6040815260006112df60408301868861127a565b82810360208401526112f281858761127a565b979650505050505050565b600060a082016001600160a01b0388168352602060a08185015281885180845260c08601915060c08160051b8701019350828a0160005b828110156113625760bf19888703018452611350868351611120565b95509284019290840190600101611334565b505050505082810360408401526113798187611120565b7fffffffff0000000000000000000000000000000000000000000000000000000086166060850152905082810360808401526113b58185611120565b98975050505050505050565b6040805190810167ffffffffffffffff811182821017156113e4576113e461124e565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156114135761141361124e565b604052919050565b600067ffffffffffffffff8211156114355761143561124e565b50601f01601f191660200190565b600082601f83011261145457600080fd5b81356114676114628261141b565b6113ea565b81815284602083860101111561147c57600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156114ac57600080fd5b823567ffffffffffffffff808211156114c457600080fd5b6114d086838701611443565b935060208501359150808211156114e657600080fd5b506114f385828601611443565b9150509250929050565b6000602080838503121561151057600080fd5b823567ffffffffffffffff8082111561152857600080fd5b818501915085601f83011261153c57600080fd5b81358181111561154e5761154e61124e565b8060051b61155d8582016113ea565b918252838101850191858101908984111561157757600080fd5b86860192505b8383101561160e578235858111156115955760008081fd5b86016040818c03601f19018113156115ad5760008081fd5b6115b56113c1565b89830135888111156115c75760008081fd5b6115d58e8c83870101611443565b8252509082013590878211156115eb5760008081fd5b6115f98d8b84860101611443565b818b015284525050918601919086019061157d565b9998505050505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561169257888303603f190185528151805187855261166688860182611120565b91890151858303868b015291905061167e8183611120565b968901969450505090860190600101611642565b509098975050505050505050565b600082601f8301126116b157600080fd5b81516116bf6114628261141b565b8181528460208386010111156116d457600080fd5b6107248260208301602087016110fc565b600080604083850312156116f857600080fd5b825167ffffffffffffffff81111561170f57600080fd5b61171b858286016116a0565b925050602083015163ffffffff8116811461173557600080fd5b809150509250929050565b60006020828403121561175257600080fd5b815180151581146107cc57600080fd5b6060815260006117756060830186611120565b82810360208401526117878186611120565b90508281036040840152610f788185611120565b6000602082840312156117ad57600080fd5b815167ffffffffffffffff8111156117c457600080fd5b610724848285016116a0565b6040815260006117e36040830185611120565b8281036020840152610b4a8185611120565b600082516118078184602087016110fc565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561078d5761078d611811565b8082018082111561078d5761078d611811565b634e487b7160e01b600052600160045260246000fd5b60006001820161187557611875611811565b5060010190565b6001600160a01b038116811461189157600080fd5b50565b6000602082840312156118a657600080fd5b81516107cc8161187c56fea2646970667358221220fe8cab828b532e5e7b2911e40131ca72978a951f8fbdcb4698a0e6c87ba00cf664736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c80637dc0d1d0116100505780637dc0d1d0146100c55780639061b923146100ec578063b4a85801146100ff57600080fd5b80633f15457f1461006c57806352539968146100b0575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100b8610112565b6040516100a7919061114c565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100b86100fa3660046111a8565b6101a0565b6100b861010d3660046111a8565b61036f565b6000805461011f90611214565b80601f016020809104026020016040519081016040528092919081815260200182805461014b90611214565b80156101985780601f1061016d57610100808354040283529160200191610198565b820191906000526020600020905b81548152906001019060200180831161017b57829003601f168201915b505050505081565b60408051600180825281830190925260609160009190816020015b60608152602001906001900390816101bb579050509050600080546101df90611214565b80601f016020809104026020016040519081016040528092919081815260200182805461020b90611214565b80156102585780601f1061022d57610100808354040283529160200191610258565b820191906000526020600020905b81548152906001019060200180831161023b57829003601f168201915b50505050508160008151811061027057610270611264565b6020026020010181905250308187876010604051602401610293939291906112a3565b60408051601f19818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f31b137b90000000000000000000000000000000000000000000000000000000017905290517fb4a858010000000000000000000000000000000000000000000000000000000091610322918c918c918c918c91016112cb565b60408051601f19818403018152908290527f556f183000000000000000000000000000000000000000000000000000000000825261036695949392916004016112fd565b60405180910390fd5b606060008061038084860186611499565b90925090506000610393878901896114fd565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bdf95fef836040518263ffffffff1660e01b81526004016103e3919061161b565b600060405180830381865afa158015610400573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261042891908101906116e5565b5090506000610437828261072c565b90505b8051516020820151101561070857600061045c82600001518360200151610793565b905061046881876107ae565b158061047d5750606082015161ffff16600114155b806104915750604082015161ffff16601014155b1561049c57506106fa565b6000806104b684600001518560a001518660c001516107d3565b90925090506001600160a01b038216156106f6576040516301ffc9a760e01b815263477cc53f60e11b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa158015610515573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105399190611740565b156105c25760405163477cc53f60e11b81526001600160a01b03831690638ef98a7e9061056e908b908b908690600401611762565b600060405180830381865afa15801561058b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105b3919081019061179b565b98505050505050505050610724565b6040516301ffc9a760e01b8152639061b92360e01b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa15801561060d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106319190611740565b1561066457604051639061b92360e01b81526001600160a01b03831690639061b9239061056e908b908b906004016117d0565b600080836001600160a01b03168960405161067f91906117f5565b600060405180830381855afa9150503d80600081146106ba576040519150601f19603f3d011682016040523d82523d6000602084013e6106bf565b606091505b509150915081156106db57995061072498505050505050505050565b896040516314d3b60360e11b8152600401610366919061114c565b5050505b61070381610922565b61043a565b50836040516314d3b60360e11b8152600401610366919061114c565b949350505050565b61077a6040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261078d81610922565b92915050565b606060006107a18484610a0a565b9050610724848483610a64565b6000815183511480156107cc57506107cc8360008460008751610ae6565b9392505050565b6000606060006107e4868686610b09565b905060058151108061083957506040805180820190915260058082527f454e5331200000000000000000000000000000000000000000000000000000006020830152610837918391600091908290610ae6565b155b1561085757505060408051602081019091526000808252915061091a565b6000610894600580845161086b9190611827565b8491907f2000000000000000000000000000000000000000000000000000000000000000610b53565b905081518111156108cb5760006108ae8360058551610bef565b604080516020810190915260008152909550935061091a92505050565b60006108d983600584610bef565b90508061090b6108ea84600161183a565b60018587516108f99190611827565b6109039190611827565b869190610a64565b9450945050505061091a565b50505b935093915050565b60c081015160208201819052815151116109395750565b600061094d82600001518360200151610a0a565b826020015161095c919061183a565b825190915061096b9082610cf9565b61ffff16604083015261097f60028261183a565b825190915061098e9082610cf9565b61ffff1660608301526109a260028261183a565b82519091506109b19082610d21565b63ffffffff1660808301526109c760048261183a565b82519091506000906109d99083610cf9565b61ffff1690506109ea60028361183a565b60a0840181905291506109fd818361183a565b60c0909301929092525050565b6000815b83518110610a1e57610a1e61184d565b6000610a2a8583610d4b565b60ff169050610a3a81600161183a565b610a44908361183a565b915080600003610a545750610a5a565b50610a0e565b6107248382611827565b8251606090610a73838561183a565b1115610a7e57600080fd5b60008267ffffffffffffffff811115610a9957610a9961124e565b6040519080825280601f01601f191660200182016040528015610ac3576020820181803683370190505b50905060208082019086860101610adb828287610d6f565b509095945050505050565b6000610af3848484610dc5565b610afe878785610dc5565b149695505050505050565b60606000610b178585610d4b565b60ff16905082610b27828661183a565b10610b3457610b3461184d565b610b4a610b4285600161183a565b869083610a64565b95945050505050565b6000835b610b61848661183a565b811015610be257827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916868281518110610b9d57610b9d611264565b01602001517fff000000000000000000000000000000000000000000000000000000000000001603610bd0579050610724565b80610bda81611863565b915050610b57565b5060001995945050505050565b6000838381518110610c0357610c03611264565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f3000000000000000000000000000000000000000000000000000000000000000148015610cbb575083610c6084600161183a565b81518110610c7057610c70611264565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f7800000000000000000000000000000000000000000000000000000000000000145b15610cee57600080610cd9610cd186600261183a565b879086610de9565b915091508015610ceb575090506107cc565b50505b610724848484610e25565b8151600090610d0983600261183a565b1115610d1457600080fd5b50016002015161ffff1690565b8151600090610d3183600461183a565b1115610d3c57600080fd5b50016004015163ffffffff1690565b6000828281518110610d5f57610d5f611264565b016020015160f81c905092915050565b60208110610da75781518352610d8660208461183a565b9250610d9360208361183a565b9150610da0602082611827565b9050610d6f565b905182516020929092036101000a6000190180199091169116179052565b8251600090610dd4838561183a565b1115610ddf57600080fd5b5091016020012090565b6000806028610df88585611827565b1015610e095750600090508061091a565b600080610e17878787610f82565b909890975095505050505050565b600080610e33858585611049565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018290529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630178b8bf90602401602060405180830381865afa158015610eb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edb9190611894565b90506001600160a01b038116610ef6576000925050506107cc565b6040517f3b3b57de000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b03821690633b3b57de90602401602060405180830381865afa158015610f54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f789190611894565b9695505050505050565b8251600090600190831115610f9657600080fd5b610fe7565b6000603a8210602f83111615610fb35750602f190190565b60478210604083111615610fc957506036190190565b60678210606083111615610fdf57506056190190565b5060ff919050565b60208501845b84811015610917576110048183015160001a610f9b565b6110166001830184015160001a610f9b565b60ff811460ff8314171561102f57600094505050610917565b60049190911b1760089490941b9390931792600201610fed565b6000806110868485875161105d9190611827565b8791907f2e00000000000000000000000000000000000000000000000000000000000000610b53565b90506000838210156110ae576110a7866110a184600161183a565b86611049565b90506110b2565b8391505b806110c9866110c18186611827565b899190610dc5565b60408051602081019390935282015260600160405160208183030381529060405280519060200120925050509392505050565b60005b838110156111175781810151838201526020016110ff565b50506000910152565b600081518084526111388160208601602086016110fc565b601f01601f19169290920160200192915050565b6020815260006107cc6020830184611120565b60008083601f84011261117157600080fd5b50813567ffffffffffffffff81111561118957600080fd5b6020830191508360208285010111156111a157600080fd5b9250929050565b600080600080604085870312156111be57600080fd5b843567ffffffffffffffff808211156111d657600080fd5b6111e28883890161115f565b909650945060208701359150808211156111fb57600080fd5b506112088782880161115f565b95989497509550505050565b600181811c9082168061122857607f821691505b60208210810361124857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6040815260006112b760408301858761127a565b905061ffff83166020830152949350505050565b6040815260006112df60408301868861127a565b82810360208401526112f281858761127a565b979650505050505050565b600060a082016001600160a01b0388168352602060a08185015281885180845260c08601915060c08160051b8701019350828a0160005b828110156113625760bf19888703018452611350868351611120565b95509284019290840190600101611334565b505050505082810360408401526113798187611120565b7fffffffff0000000000000000000000000000000000000000000000000000000086166060850152905082810360808401526113b58185611120565b98975050505050505050565b6040805190810167ffffffffffffffff811182821017156113e4576113e461124e565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156114135761141361124e565b604052919050565b600067ffffffffffffffff8211156114355761143561124e565b50601f01601f191660200190565b600082601f83011261145457600080fd5b81356114676114628261141b565b6113ea565b81815284602083860101111561147c57600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156114ac57600080fd5b823567ffffffffffffffff808211156114c457600080fd5b6114d086838701611443565b935060208501359150808211156114e657600080fd5b506114f385828601611443565b9150509250929050565b6000602080838503121561151057600080fd5b823567ffffffffffffffff8082111561152857600080fd5b818501915085601f83011261153c57600080fd5b81358181111561154e5761154e61124e565b8060051b61155d8582016113ea565b918252838101850191858101908984111561157757600080fd5b86860192505b8383101561160e578235858111156115955760008081fd5b86016040818c03601f19018113156115ad5760008081fd5b6115b56113c1565b89830135888111156115c75760008081fd5b6115d58e8c83870101611443565b8252509082013590878211156115eb5760008081fd5b6115f98d8b84860101611443565b818b015284525050918601919086019061157d565b9998505050505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561169257888303603f190185528151805187855261166688860182611120565b91890151858303868b015291905061167e8183611120565b968901969450505090860190600101611642565b509098975050505050505050565b600082601f8301126116b157600080fd5b81516116bf6114628261141b565b8181528460208386010111156116d457600080fd5b6107248260208301602087016110fc565b600080604083850312156116f857600080fd5b825167ffffffffffffffff81111561170f57600080fd5b61171b858286016116a0565b925050602083015163ffffffff8116811461173557600080fd5b809150509250929050565b60006020828403121561175257600080fd5b815180151581146107cc57600080fd5b6060815260006117756060830186611120565b82810360208401526117878186611120565b90508281036040840152610f788185611120565b6000602082840312156117ad57600080fd5b815167ffffffffffffffff8111156117c457600080fd5b610724848285016116a0565b6040815260006117e36040830185611120565b8281036020840152610b4a8185611120565b600082516118078184602087016110fc565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561078d5761078d611811565b8082018082111561078d5761078d611811565b634e487b7160e01b600052600160045260246000fd5b60006001820161187557611875611811565b5060010190565b6001600160a01b038116811461189157600080fd5b50565b6000602082840312156118a657600080fd5b81516107cc8161187c56fea2646970667358221220fe8cab828b532e5e7b2911e40131ca72978a951f8fbdcb4698a0e6c87ba00cf664736f6c63430008110033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 4867, + "contract": "contracts/dnsregistrar/OffchainDNSResolver.sol:OffchainDNSResolver", + "label": "gatewayURL", + "offset": 0, + "slot": "0", + "type": "t_string_storage" + } + ], + "types": { + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/sepolia/P256SHA256Algorithm.json b/deployments/sepolia/P256SHA256Algorithm.json new file mode 100644 index 00000000..0b3eeffb --- /dev/null +++ b/deployments/sepolia/P256SHA256Algorithm.json @@ -0,0 +1,82 @@ +{ + "address": "0x2CECc45151379e54EAdc9b6474D6a4aa0D795891", + "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" + } + ], + "transactionHash": "0x272f8b2b8596b22efdb564b15a475b360728ed09c2f49dfcf5c9bef0560dcb9d", + "receipt": { + "to": null, + "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8", + "contractAddress": "0x2CECc45151379e54EAdc9b6474D6a4aa0D795891", + "transactionIndex": 51, + "gasUsed": "896222", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x6bc4426587cfe834bdd7e7d69788e30cdda4bb07bc110461b34517ededa6b3f2", + "transactionHash": "0x272f8b2b8596b22efdb564b15a475b360728ed09c2f49dfcf5c9bef0560dcb9d", + "logs": [], + "blockNumber": 4091599, + "cumulativeGasUsed": "17141949", + "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", + "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 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/sepolia/RSASHA1Algorithm.json b/deployments/sepolia/RSASHA1Algorithm.json new file mode 100644 index 00000000..788823f5 --- /dev/null +++ b/deployments/sepolia/RSASHA1Algorithm.json @@ -0,0 +1,71 @@ +{ + "address": "0x2fa4EC8291aD6c90a6107A5E9447384A41A59e43", + "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" + } + ], + "transactionHash": "0x959ce47268a2a741fe5a3a349b75fae34718be2905cfb9ba81d61a4b564933bc", + "receipt": { + "to": null, + "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8", + "contractAddress": "0x2fa4EC8291aD6c90a6107A5E9447384A41A59e43", + "transactionIndex": 71, + "gasUsed": "695194", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa140af3b835d7359897fcd31fa0972ef7d95deaedb13ab2bd8be2cc83ccd608a", + "transactionHash": "0x959ce47268a2a741fe5a3a349b75fae34718be2905cfb9ba81d61a4b564933bc", + "logs": [], + "blockNumber": 4091594, + "cumulativeGasUsed": "4023217", + "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", + "devdoc": { + "details": "Implements the DNSSEC RSASHA1 algorithm.", + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/sepolia/RSASHA256Algorithm.json b/deployments/sepolia/RSASHA256Algorithm.json new file mode 100644 index 00000000..45410c5a --- /dev/null +++ b/deployments/sepolia/RSASHA256Algorithm.json @@ -0,0 +1,71 @@ +{ + "address": "0x9136A7050849e6DcA30BB9A54c8d0F11a13AAB48", + "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" + } + ], + "transactionHash": "0x8e97e86172c23421c881cd5db60318fd9f7714c782487a08c0da1427269eb0bc", + "receipt": { + "to": null, + "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8", + "contractAddress": "0x9136A7050849e6DcA30BB9A54c8d0F11a13AAB48", + "transactionIndex": 48, + "gasUsed": "448967", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x0d435152d4eba03d76c3bda4384e2ca8b011e422d4da6a3877db129a6e2150fd", + "transactionHash": "0x8e97e86172c23421c881cd5db60318fd9f7714c782487a08c0da1427269eb0bc", + "logs": [], + "blockNumber": 4091595, + "cumulativeGasUsed": "5527528", + "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", + "devdoc": { + "details": "Implements the DNSSEC RSASHA256 algorithm.", + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/sepolia/SHA1Digest.json b/deployments/sepolia/SHA1Digest.json new file mode 100644 index 00000000..8b0219af --- /dev/null +++ b/deployments/sepolia/SHA1Digest.json @@ -0,0 +1,77 @@ +{ + "address": "0xE66B451d56e6e88261Ae9D7C1BF30960145c0e1c", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xbda2b18c488e4cd5ec60f7fad77d82709a31e7dae6161cff7b81e3d5769a2e67", + "receipt": { + "to": null, + "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8", + "contractAddress": "0xE66B451d56e6e88261Ae9D7C1BF30960145c0e1c", + "transactionIndex": 142, + "gasUsed": "459448", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x30acd24b189054907ecaed28d68247b4242bd84dbf37b6da7fad46bbe8c52dd7", + "transactionHash": "0xbda2b18c488e4cd5ec60f7fad77d82709a31e7dae6161cff7b81e3d5769a2e67", + "logs": [], + "blockNumber": 4091631, + "cumulativeGasUsed": "25867642", + "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\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements the DNSSEC SHA1 digest.\",\"kind\":\"dev\",\"methods\":{\"verify(bytes,bytes)\":{\"details\":\"Verifies a cryptographic hash.\",\"params\":{\"data\":\"The data to hash.\",\"hash\":\"The hash to compare to.\"},\"returns\":{\"_0\":\"True iff the hashed data matches the provided hash value.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/digests/SHA1Digest.sol\":\"SHA1Digest\"},\"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/digests/Digest.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @dev An interface for contracts implementing a DNSSEC digest.\\n */\\ninterface Digest {\\n /**\\n * @dev Verifies a cryptographic hash.\\n * @param data The data to hash.\\n * @param hash The hash to compare to.\\n * @return True iff the hashed data matches the provided hash value.\\n */\\n function verify(\\n bytes calldata data,\\n bytes calldata hash\\n ) external pure virtual returns (bool);\\n}\\n\",\"keccak256\":\"0x8ea926b2db0578c4ad7fce4582fc0f6f0f9efee8dca2085dbdb9984f18941e28\"},\"contracts/dnssec-oracle/digests/SHA1Digest.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Digest.sol\\\";\\nimport \\\"../BytesUtils.sol\\\";\\nimport \\\"@ensdomains/solsha1/contracts/SHA1.sol\\\";\\n\\n/**\\n * @dev Implements the DNSSEC SHA1 digest.\\n */\\ncontract SHA1Digest is Digest {\\n using BytesUtils for *;\\n\\n function verify(\\n bytes calldata data,\\n bytes calldata hash\\n ) external pure override returns (bool) {\\n require(hash.length == 20, \\\"Invalid sha1 hash length\\\");\\n bytes32 expected = hash.readBytes20(0);\\n bytes20 computed = SHA1.sha1(data);\\n return expected == computed;\\n }\\n}\\n\",\"keccak256\":\"0x56f4e188f9c5ea120354ff4d00555c3b76b5837be00a1564fed608e22a7dc8aa\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061076c806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f7e83aee14610030575b600080fd5b61004361003e36600461068a565b610057565b604051901515815260200160405180910390f35b6000601482146100c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420736861312068617368206c656e6774680000000000000000604482015260640160405180910390fd5b600061010d600085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061017c9050565b6bffffffffffffffffffffffff19169050600061015f87878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101af92505050565b6bffffffffffffffffffffffff1916919091149695505050505050565b815160009061018c8360146106f6565b111561019757600080fd5b5001602001516bffffffffffffffffffffffff191690565b60006040518251602084019350604067ffffffffffffffc0600183011601600982820310600181036101e2576040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f0610235565b60008383101561022e5750808201519282900392602084101561022e5760001960208590036101000a0119165b9392505050565b60005b828110156105c15761024b848289610201565b855261025b846020830189610201565b6020860152604081850310600181036102775760808286038701535b506040830381146001810361029457602086018051600887021790525b5060405b608081101561031c57858101603f19810151603719820151601f19830151600b198401516002911891909218189081027ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe1663800000009091047c010000000100000001000000010000000100000001000000010000000116179052600c01610298565b5060805b6101408110156103a557858101607f19810151606f19820151603f198301516017198401516004911891909218189081027ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc1663400000009091047c030000000300000003000000030000000300000003000000030000000316179052601801610320565b508160008060005b6050811015610597576014810480156103dd576001811461040d576002811461043b576003811461046e57610498565b6501000000000085046a010000000000000000000086048118600160781b870416189350635a8279999250610498565b650100000000008504600160781b86046a0100000000000000000000870418189350636ed9eba19250610498565b6a01000000000000000000008504600160781b8604818117650100000000008804169116179350638f1bbcdc9250610498565b650100000000008504600160781b86046a010000000000000000000087041818935063ca62c1d692505b50601f770800000000000000000000000000000000000000000000008504168063ffffffe073080000000000000000000000000000000000000087041617905080840190508063ffffffff86160190508083019050807c0100000000000000000000000000000000000000000000000000000000600484028c015104019050740100000000000000000000000000000000000000008102650100000000008604179450506a0100000000000000000000633fffffff6a040000000000000000000086041663c00000006604000000000000870416170277ffffffff00ffffffff000000000000ffffffff00ffffffff85161793506001810190506103ad565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff1690604001610238565b506c0100000000000000000000000063ffffffff821667ffffffff000000006101008404166bffffffff0000000000000000620100008504166fffffffff000000000000000000000000630100000086041673ffffffff000000000000000000000000000000006401000000008704161717171702945050505050919050565b60008083601f84011261065357600080fd5b50813567ffffffffffffffff81111561066b57600080fd5b60208301915083602082850101111561068357600080fd5b9250929050565b600080600080604085870312156106a057600080fd5b843567ffffffffffffffff808211156106b857600080fd5b6106c488838901610641565b909650945060208701359150808211156106dd57600080fd5b506106ea87828801610641565b95989497509550505050565b80820180821115610730577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea26469706673582212201eb056a89a6b6b67ba5acc9d1d278299eadfc218cf0f5baba761aa60461f441964736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f7e83aee14610030575b600080fd5b61004361003e36600461068a565b610057565b604051901515815260200160405180910390f35b6000601482146100c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420736861312068617368206c656e6774680000000000000000604482015260640160405180910390fd5b600061010d600085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061017c9050565b6bffffffffffffffffffffffff19169050600061015f87878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101af92505050565b6bffffffffffffffffffffffff1916919091149695505050505050565b815160009061018c8360146106f6565b111561019757600080fd5b5001602001516bffffffffffffffffffffffff191690565b60006040518251602084019350604067ffffffffffffffc0600183011601600982820310600181036101e2576040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f0610235565b60008383101561022e5750808201519282900392602084101561022e5760001960208590036101000a0119165b9392505050565b60005b828110156105c15761024b848289610201565b855261025b846020830189610201565b6020860152604081850310600181036102775760808286038701535b506040830381146001810361029457602086018051600887021790525b5060405b608081101561031c57858101603f19810151603719820151601f19830151600b198401516002911891909218189081027ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe1663800000009091047c010000000100000001000000010000000100000001000000010000000116179052600c01610298565b5060805b6101408110156103a557858101607f19810151606f19820151603f198301516017198401516004911891909218189081027ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc1663400000009091047c030000000300000003000000030000000300000003000000030000000316179052601801610320565b508160008060005b6050811015610597576014810480156103dd576001811461040d576002811461043b576003811461046e57610498565b6501000000000085046a010000000000000000000086048118600160781b870416189350635a8279999250610498565b650100000000008504600160781b86046a0100000000000000000000870418189350636ed9eba19250610498565b6a01000000000000000000008504600160781b8604818117650100000000008804169116179350638f1bbcdc9250610498565b650100000000008504600160781b86046a010000000000000000000087041818935063ca62c1d692505b50601f770800000000000000000000000000000000000000000000008504168063ffffffe073080000000000000000000000000000000000000087041617905080840190508063ffffffff86160190508083019050807c0100000000000000000000000000000000000000000000000000000000600484028c015104019050740100000000000000000000000000000000000000008102650100000000008604179450506a0100000000000000000000633fffffff6a040000000000000000000086041663c00000006604000000000000870416170277ffffffff00ffffffff000000000000ffffffff00ffffffff85161793506001810190506103ad565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff1690604001610238565b506c0100000000000000000000000063ffffffff821667ffffffff000000006101008404166bffffffff0000000000000000620100008504166fffffffff000000000000000000000000630100000086041673ffffffff000000000000000000000000000000006401000000008704161717171702945050505050919050565b60008083601f84011261065357600080fd5b50813567ffffffffffffffff81111561066b57600080fd5b60208301915083602082850101111561068357600080fd5b9250929050565b600080600080604085870312156106a057600080fd5b843567ffffffffffffffff808211156106b857600080fd5b6106c488838901610641565b909650945060208701359150808211156106dd57600080fd5b506106ea87828801610641565b95989497509550505050565b80820180821115610730577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea26469706673582212201eb056a89a6b6b67ba5acc9d1d278299eadfc218cf0f5baba761aa60461f441964736f6c63430008110033", + "devdoc": { + "details": "Implements the DNSSEC SHA1 digest.", + "kind": "dev", + "methods": { + "verify(bytes,bytes)": { + "details": "Verifies a cryptographic hash.", + "params": { + "data": "The data to hash.", + "hash": "The hash to compare to." + }, + "returns": { + "_0": "True iff the hashed data matches the provided hash value." + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/sepolia/SHA256Digest.json b/deployments/sepolia/SHA256Digest.json new file mode 100644 index 00000000..dd995c07 --- /dev/null +++ b/deployments/sepolia/SHA256Digest.json @@ -0,0 +1,76 @@ +{ + "address": "0x79eb4d789f9201e82d9c1a794a789d12c00e9a3c", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xc701473686252cd4f570061c2dcfa60fdc9b861e81de17d37e141c982e02f4f2", + "receipt": { + "to": null, + "from": "0x4fe4e666be5752f1fdd210f4ab5de2cc26e3e0e8", + "contractAddress": "0x79eb4d789f9201e82d9c1a794a789d12c00e9a3c", + "transactionIndex": "0x88", + "gasUsed": "0x3396e", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x971489131848c07268e782f1d35b69c2c18920a9bfac95d42ea6baab63399b61", + "transactionHash": "0xc701473686252cd4f570061c2dcfa60fdc9b861e81de17d37e141c982e02f4f2", + "logs": [], + "blockNumber": "0x3e6f2b", + "cumulativeGasUsed": "0x1a3ffc5", + "status": "0x1" + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "e04502f562d98d0455f6c1c453418cdd", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements the DNSSEC SHA256 digest.\",\"kind\":\"dev\",\"methods\":{\"verify(bytes,bytes)\":{\"details\":\"Verifies a cryptographic hash.\",\"params\":{\"data\":\"The data to hash.\",\"hash\":\"The hash to compare to.\"},\"returns\":{\"_0\":\"True iff the hashed data matches the provided hash value.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/digests/SHA256Digest.sol\":\"SHA256Digest\"},\"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/digests/Digest.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @dev An interface for contracts implementing a DNSSEC digest.\\n */\\ninterface Digest {\\n /**\\n * @dev Verifies a cryptographic hash.\\n * @param data The data to hash.\\n * @param hash The hash to compare to.\\n * @return True iff the hashed data matches the provided hash value.\\n */\\n function verify(\\n bytes calldata data,\\n bytes calldata hash\\n ) external pure virtual returns (bool);\\n}\\n\",\"keccak256\":\"0x8ea926b2db0578c4ad7fce4582fc0f6f0f9efee8dca2085dbdb9984f18941e28\"},\"contracts/dnssec-oracle/digests/SHA256Digest.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Digest.sol\\\";\\nimport \\\"../BytesUtils.sol\\\";\\n\\n/**\\n * @dev Implements the DNSSEC SHA256 digest.\\n */\\ncontract SHA256Digest is Digest {\\n using BytesUtils for *;\\n\\n function verify(\\n bytes calldata data,\\n bytes calldata hash\\n ) external pure override returns (bool) {\\n require(hash.length == 32, \\\"Invalid sha256 hash length\\\");\\n return sha256(data) == hash.readBytes32(0);\\n }\\n}\\n\",\"keccak256\":\"0x0531c6764434ea17d967f079ed2299b1f83606e891dbdaa92500d43ef64cf126\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506102df806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f7e83aee14610030575b600080fd5b61004361003e3660046101d4565b610057565b604051901515815260200160405180910390f35b6000602082146100c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c6964207368613235362068617368206c656e677468000000000000604482015260640160405180910390fd5b61010b600084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506101679050565b6002868660405161011d929190610240565b602060405180830381855afa15801561013a573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061015d9190610250565b1495945050505050565b8151600090610177836020610269565b111561018257600080fd5b50016020015190565b60008083601f84011261019d57600080fd5b50813567ffffffffffffffff8111156101b557600080fd5b6020830191508360208285010111156101cd57600080fd5b9250929050565b600080600080604085870312156101ea57600080fd5b843567ffffffffffffffff8082111561020257600080fd5b61020e8883890161018b565b9096509450602087013591508082111561022757600080fd5b506102348782880161018b565b95989497509550505050565b8183823760009101908152919050565b60006020828403121561026257600080fd5b5051919050565b808201808211156102a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea26469706673582212202348aaafc43a5bd6086d9011d799efff422cd74c984a03fe13c85cc4d45e842b64736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f7e83aee14610030575b600080fd5b61004361003e3660046101d4565b610057565b604051901515815260200160405180910390f35b6000602082146100c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c6964207368613235362068617368206c656e677468000000000000604482015260640160405180910390fd5b61010b600084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506101679050565b6002868660405161011d929190610240565b602060405180830381855afa15801561013a573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061015d9190610250565b1495945050505050565b8151600090610177836020610269565b111561018257600080fd5b50016020015190565b60008083601f84011261019d57600080fd5b50813567ffffffffffffffff8111156101b557600080fd5b6020830191508360208285010111156101cd57600080fd5b9250929050565b600080600080604085870312156101ea57600080fd5b843567ffffffffffffffff8082111561020257600080fd5b61020e8883890161018b565b9096509450602087013591508082111561022757600080fd5b506102348782880161018b565b95989497509550505050565b8183823760009101908152919050565b60006020828403121561026257600080fd5b5051919050565b808201808211156102a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea26469706673582212202348aaafc43a5bd6086d9011d799efff422cd74c984a03fe13c85cc4d45e842b64736f6c63430008110033", + "devdoc": { + "details": "Implements the DNSSEC SHA256 digest.", + "kind": "dev", + "methods": { + "verify(bytes,bytes)": { + "details": "Verifies a cryptographic hash.", + "params": { + "data": "The data to hash.", + "hash": "The hash to compare to." + }, + "returns": { + "_0": "True iff the hashed data matches the provided hash value." + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/sepolia/TLDPublicSuffixList.json b/deployments/sepolia/TLDPublicSuffixList.json new file mode 100644 index 00000000..85630853 --- /dev/null +++ b/deployments/sepolia/TLDPublicSuffixList.json @@ -0,0 +1,61 @@ +{ + "address": "0x41b1a43Af05e484B36b1322Af1F798970E8a8ce8", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "isPublicSuffix", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xaa078240db59f5745ef1067ae9e4dd005f589da008b99454714cd13573ed3628", + "receipt": { + "to": null, + "from": "0x4Fe4e666Be5752f1FdD210F4Ab5DE2Cc26e3E0e8", + "contractAddress": "0x41b1a43Af05e484B36b1322Af1F798970E8a8ce8", + "transactionIndex": 185, + "gasUsed": "166669", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf1fe4cb67cb97367c921f3446f0dc305daa2d74e5e1d83dec137f6b4864b7b59", + "transactionHash": "0xaa078240db59f5745ef1067ae9e4dd005f589da008b99454714cd13573ed3628", + "logs": [], + "blockNumber": 4091743, + "cumulativeGasUsed": "23963422", + "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\":\"name\",\"type\":\"bytes\"}],\"name\":\"isPublicSuffix\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"A public suffix list that treats all TLDs as public suffixes.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnsregistrar/TLDPublicSuffixList.sol\":\"TLDPublicSuffixList\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"contracts/dnsregistrar/PublicSuffixList.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\ninterface PublicSuffixList {\\n function isPublicSuffix(bytes calldata name) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x12158ba8838ee2b1ebb0178a52d2f4d54dcc68282d569226e62afc2b0dccbbac\"},\"contracts/dnsregistrar/TLDPublicSuffixList.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"../dnssec-oracle/BytesUtils.sol\\\";\\nimport \\\"./PublicSuffixList.sol\\\";\\n\\n/**\\n * @dev A public suffix list that treats all TLDs as public suffixes.\\n */\\ncontract TLDPublicSuffixList is PublicSuffixList {\\n using BytesUtils for bytes;\\n\\n function isPublicSuffix(\\n bytes calldata name\\n ) external view override returns (bool) {\\n uint256 labellen = name.readUint8(0);\\n return labellen > 0 && name.readUint8(labellen + 1) == 0;\\n }\\n}\\n\",\"keccak256\":\"0x0e64dc888396ef3c88e64afbf4e35fb107fa416174b97223d0b4894e5e085e53\"},\"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\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061020d806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80634f89059e14610030575b600080fd5b61004361003e36600461012e565b610057565b604051901515815260200160405180910390f35b60008061009e600085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061010a9050565b60ff16905060008111801561010057506100fb6100bc8260016101a0565b85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061010a9050565b60ff16155b9150505b92915050565b600082828151811061011e5761011e6101c1565b016020015160f81c905092915050565b6000806020838503121561014157600080fd5b823567ffffffffffffffff8082111561015957600080fd5b818501915085601f83011261016d57600080fd5b81358181111561017c57600080fd5b86602082850101111561018e57600080fd5b60209290920196919550909350505050565b8082018082111561010457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fdfea2646970667358221220bd314730014c3187d1d82d4d375c5edf3ba7a6a9750141e8ca0924a3c4dec52b64736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80634f89059e14610030575b600080fd5b61004361003e36600461012e565b610057565b604051901515815260200160405180910390f35b60008061009e600085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061010a9050565b60ff16905060008111801561010057506100fb6100bc8260016101a0565b85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505061010a9050565b60ff16155b9150505b92915050565b600082828151811061011e5761011e6101c1565b016020015160f81c905092915050565b6000806020838503121561014157600080fd5b823567ffffffffffffffff8082111561015957600080fd5b818501915085601f83011261016d57600080fd5b81358181111561017c57600080fd5b86602082850101111561018e57600080fd5b60209290920196919550909350505050565b8082018082111561010457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fdfea2646970667358221220bd314730014c3187d1d82d4d375c5edf3ba7a6a9750141e8ca0924a3c4dec52b64736f6c63430008110033", + "devdoc": { + "details": "A public suffix list that treats all TLDs as public suffixes.", + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file