{
  "address": "0x2FbEcE7fD8E6ceF6eB0F962FEDBEe95374fc3C2A",
  "transactionHash": "0x9803c6afed45bfd399e34479523ef527c38a85dc84de7c4b56da51cb9ed245b2",
  "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": "0x9803c6afed45bfd399e34479523ef527c38a85dc84de7c4b56da51cb9ed245b2",
  "receipt": {
    "to": null,
    "from": "0xa303ddC620aa7d1390BACcc8A495508B183fab59",
    "contractAddress": "0x2FbEcE7fD8E6ceF6eB0F962FEDBEe95374fc3C2A",
    "transactionIndex": 3,
    "gasUsed": "1013169",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x16d6df256ff9565bcfcb245d2440f301f7eb11a2b389c6826d93cb3d48242d19",
    "transactionHash": "0x9803c6afed45bfd399e34479523ef527c38a85dc84de7c4b56da51cb9ed245b2",
    "logs": [],
    "blockNumber": 6470032,
    "cumulativeGasUsed": "1172642",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "solcInputHash": "7948b60c3b601df824761a337a51d661",
  "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"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\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/dnssec-oracle/BytesUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary BytesUtils {\\n    /*\\n    * @dev Returns the keccak-256 hash of a byte range.\\n    * @param self The byte string to hash.\\n    * @param offset The position to start hashing at.\\n    * @param len The number of bytes to hash.\\n    * @return The hash of the byte range.\\n    */\\n    function keccak(bytes memory self, uint offset, uint len) internal pure returns (bytes32 ret) {\\n        require(offset + len <= self.length);\\n        assembly {\\n            ret := keccak256(add(add(self, 32), offset), len)\\n        }\\n    }\\n\\n\\n    /*\\n    * @dev Returns a positive number if `other` comes lexicographically after\\n    *      `self`, a negative number if it comes before, or zero if the\\n    *      contents of the two bytes are equal.\\n    * @param self The first bytes to compare.\\n    * @param other The second bytes to compare.\\n    * @return The result of the comparison.\\n    */\\n    function compare(bytes memory self, bytes memory other) internal pure returns (int) {\\n        return compare(self, 0, self.length, other, 0, other.length);\\n    }\\n\\n    /*\\n    * @dev Returns a positive number if `other` comes lexicographically after\\n    *      `self`, a negative number if it comes before, or zero if the\\n    *      contents of the two bytes are equal. Comparison is done per-rune,\\n    *      on unicode codepoints.\\n    * @param self The first bytes to compare.\\n    * @param offset The offset of self.\\n    * @param len    The length of self.\\n    * @param other The second bytes to compare.\\n    * @param otheroffset The offset of the other string.\\n    * @param otherlen    The length of the other string.\\n    * @return The result of the comparison.\\n    */\\n    function compare(bytes memory self, uint offset, uint len, bytes memory other, uint otheroffset, uint otherlen) internal pure returns (int) {\\n        uint shortest = len;\\n        if (otherlen < len)\\n        shortest = otherlen;\\n\\n        uint selfptr;\\n        uint otherptr;\\n\\n        assembly {\\n            selfptr := add(self, add(offset, 32))\\n            otherptr := add(other, add(otheroffset, 32))\\n        }\\n        for (uint idx = 0; idx < shortest; idx += 32) {\\n            uint a;\\n            uint b;\\n            assembly {\\n                a := mload(selfptr)\\n                b := mload(otherptr)\\n            }\\n            if (a != b) {\\n                // Mask out irrelevant bytes and check again\\n                uint mask;\\n                if (shortest > 32) {\\n                    mask = type(uint256).max;\\n                } else {\\n                    mask = ~(2 ** (8 * (32 - shortest + idx)) - 1);\\n                }\\n                int diff = int(a & mask) - int(b & mask);\\n                if (diff != 0)\\n                return diff;\\n            }\\n            selfptr += 32;\\n            otherptr += 32;\\n        }\\n\\n        return int(len) - int(otherlen);\\n    }\\n\\n    /*\\n    * @dev Returns true if the two byte ranges are equal.\\n    * @param self The first byte range to compare.\\n    * @param offset The offset into the first byte range.\\n    * @param other The second byte range to compare.\\n    * @param otherOffset The offset into the second byte range.\\n    * @param len The number of bytes to compare\\n    * @return True if the byte ranges are equal, false otherwise.\\n    */\\n    function equals(bytes memory self, uint offset, bytes memory other, uint otherOffset, uint len) internal pure returns (bool) {\\n        return keccak(self, offset, len) == keccak(other, otherOffset, len);\\n    }\\n\\n    /*\\n    * @dev Returns true if the two byte ranges are equal with offsets.\\n    * @param self The first byte range to compare.\\n    * @param offset The offset into the first byte range.\\n    * @param other The second byte range to compare.\\n    * @param otherOffset The offset into the second byte range.\\n    * @return True if the byte ranges are equal, false otherwise.\\n    */\\n    function equals(bytes memory self, uint offset, bytes memory other, uint otherOffset) internal pure returns (bool) {\\n        return keccak(self, offset, self.length - offset) == keccak(other, otherOffset, other.length - otherOffset);\\n    }\\n\\n    /*\\n    * @dev Compares a range of 'self' to all of 'other' and returns True iff\\n    *      they are equal.\\n    * @param self The first byte range to compare.\\n    * @param offset The offset into the first byte range.\\n    * @param other The second byte range to compare.\\n    * @return True if the byte ranges are equal, false otherwise.\\n    */\\n    function equals(bytes memory self, uint offset, bytes memory other) internal pure returns (bool) {\\n        return self.length >= offset + other.length && equals(self, offset, other, 0, other.length);\\n    }\\n\\n    /*\\n    * @dev Returns true if the two byte ranges are equal.\\n    * @param self The first byte range to compare.\\n    * @param other The second byte range to compare.\\n    * @return True if the byte ranges are equal, false otherwise.\\n    */\\n    function equals(bytes memory self, bytes memory other) internal pure returns(bool) {\\n        return self.length == other.length && equals(self, 0, other, 0, self.length);\\n    }\\n\\n    /*\\n    * @dev Returns the 8-bit number at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes\\n    * @return The specified 8 bits of the string, interpreted as an integer.\\n    */\\n    function readUint8(bytes memory self, uint idx) internal pure returns (uint8 ret) {\\n        return uint8(self[idx]);\\n    }\\n\\n    /*\\n    * @dev Returns the 16-bit number at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes\\n    * @return The specified 16 bits of the string, interpreted as an integer.\\n    */\\n    function readUint16(bytes memory self, uint idx) internal pure returns (uint16 ret) {\\n        require(idx + 2 <= self.length);\\n        assembly {\\n            ret := and(mload(add(add(self, 2), idx)), 0xFFFF)\\n        }\\n    }\\n\\n    /*\\n    * @dev Returns the 32-bit number at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes\\n    * @return The specified 32 bits of the string, interpreted as an integer.\\n    */\\n    function readUint32(bytes memory self, uint idx) internal pure returns (uint32 ret) {\\n        require(idx + 4 <= self.length);\\n        assembly {\\n            ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF)\\n        }\\n    }\\n\\n    /*\\n    * @dev Returns the 32 byte value at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes\\n    * @return The specified 32 bytes of the string.\\n    */\\n    function readBytes32(bytes memory self, uint idx) internal pure returns (bytes32 ret) {\\n        require(idx + 32 <= self.length);\\n        assembly {\\n            ret := mload(add(add(self, 32), idx))\\n        }\\n    }\\n\\n    /*\\n    * @dev Returns the 32 byte value at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes\\n    * @return The specified 32 bytes of the string.\\n    */\\n    function readBytes20(bytes memory self, uint idx) internal pure returns (bytes20 ret) {\\n        require(idx + 20 <= self.length);\\n        assembly {\\n            ret := and(mload(add(add(self, 32), idx)), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000)\\n        }\\n    }\\n\\n    /*\\n    * @dev Returns the n byte value at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes.\\n    * @param len The number of bytes.\\n    * @return The specified 32 bytes of the string.\\n    */\\n    function readBytesN(bytes memory self, uint idx, uint len) internal pure returns (bytes32 ret) {\\n        require(len <= 32);\\n        require(idx + len <= self.length);\\n        assembly {\\n            let mask := not(sub(exp(256, sub(32, len)), 1))\\n            ret := and(mload(add(add(self, 32), idx)),  mask)\\n        }\\n    }\\n\\n    function memcpy(uint dest, uint src, uint len) private pure {\\n        // Copy word-length chunks while possible\\n        for (; len >= 32; len -= 32) {\\n            assembly {\\n                mstore(dest, mload(src))\\n            }\\n            dest += 32;\\n            src += 32;\\n        }\\n\\n        // Copy remaining bytes\\n        unchecked {\\n            uint mask = (256 ** (32 - len)) - 1;\\n            assembly {\\n                let srcpart := and(mload(src), not(mask))\\n                let destpart := and(mload(dest), mask)\\n                mstore(dest, or(destpart, srcpart))\\n            }\\n        }\\n    }\\n\\n    /*\\n    * @dev Copies a substring into a new byte string.\\n    * @param self The byte string to copy from.\\n    * @param offset The offset to start copying at.\\n    * @param len The number of bytes to copy.\\n    */\\n    function substring(bytes memory self, uint offset, uint len) internal pure returns(bytes memory) {\\n        require(offset + len <= self.length);\\n\\n        bytes memory ret = new bytes(len);\\n        uint dest;\\n        uint src;\\n\\n        assembly {\\n            dest := add(ret, 32)\\n            src := add(add(self, 32), offset)\\n        }\\n        memcpy(dest, src, len);\\n\\n        return ret;\\n    }\\n\\n    // Maps characters from 0x30 to 0x7A to their base32 values.\\n    // 0xFF represents invalid characters in that range.\\n    bytes constant base32HexTable = hex'00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F';\\n\\n    /**\\n     * @dev Decodes unpadded base32 data of up to one word in length.\\n     * @param self The data to decode.\\n     * @param off Offset into the string to start at.\\n     * @param len Number of characters to decode.\\n     * @return The decoded data, left aligned.\\n     */\\n    function base32HexDecodeWord(bytes memory self, uint off, uint len) internal pure returns(bytes32) {\\n        require(len <= 52);\\n\\n        uint ret = 0;\\n        uint8 decoded;\\n        for(uint i = 0; i < len; i++) {\\n            bytes1 char = self[off + i];\\n            require(char >= 0x30 && char <= 0x7A);\\n            decoded = uint8(base32HexTable[uint(uint8(char)) - 0x30]);\\n            require(decoded <= 0x20);\\n            if(i == len - 1) {\\n                break;\\n            }\\n            ret = (ret << 5) | decoded;\\n        }\\n\\n        uint bitlen = len * 5;\\n        if(len % 8 == 0) {\\n            // Multiple of 8 characters, no padding\\n            ret = (ret << 5) | decoded;\\n        } else if(len % 8 == 2) {\\n            // Two extra characters - 1 byte\\n            ret = (ret << 3) | (decoded >> 2);\\n            bitlen -= 2;\\n        } else if(len % 8 == 4) {\\n            // Four extra characters - 2 bytes\\n            ret = (ret << 1) | (decoded >> 4);\\n            bitlen -= 4;\\n        } else if(len % 8 == 5) {\\n            // Five extra characters - 3 bytes\\n            ret = (ret << 4) | (decoded >> 1);\\n            bitlen -= 1;\\n        } else if(len % 8 == 7) {\\n            // Seven extra characters - 4 bytes\\n            ret = (ret << 2) | (decoded >> 3);\\n            bitlen -= 3;\\n        } else {\\n            revert();\\n        }\\n\\n        return bytes32(ret << (256 - bitlen));\\n    }\\n}\",\"keccak256\":\"0x83315df2e54c74451577c70da2c267c3459802b08b9aeec6516302eee70f796e\"},\"contracts/dnssec-oracle/algorithms/Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n* @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\\n*/\\ninterface Algorithm {\\n    /**\\n    * @dev Verifies a signature.\\n    * @param key The public key to verify with.\\n    * @param data The signed data to verify.\\n    * @param signature The signature to verify.\\n    * @return True iff the signature is valid.\\n    */\\n    function verify(bytes calldata key, bytes calldata data, bytes calldata signature) external virtual view returns (bool);\\n}\\n\",\"keccak256\":\"0x51d6251568844e435f58952354abe8c8c8e978ab40ecb0bbb2f5bd767838b3a7\"},\"contracts/dnssec-oracle/algorithms/EllipticCurve.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @title   EllipticCurve\\n *\\n * @author  Tilman Drerup;\\n *\\n * @notice  Implements elliptic curve math; Parametrized for SECP256R1.\\n *\\n *          Includes components of code by Andreas Olofsson, Alexander Vlasov\\n *          (https://github.com/BANKEX/CurveArithmetics), and Avi Asayag\\n *          (https://github.com/orbs-network/elliptic-curve-solidity)\\n *\\n *          Source: https://github.com/tdrerup/elliptic-curve-solidity\\n *\\n * @dev     NOTE: To disambiguate public keys when verifying signatures, activate\\n *          condition 'rs[1] > lowSmax' in validateSignature().\\n */\\ncontract EllipticCurve {\\n\\n    // Set parameters for curve.\\n    uint constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\\n    uint constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\\n    uint constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\\n    uint constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\\n    uint constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n    uint constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\\n\\n    uint constant lowSmax = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0;\\n\\n    /**\\n     * @dev Inverse of u in the field of modulo m.\\n     */\\n    function inverseMod(uint u, uint m) internal pure\\n        returns (uint)\\n    {\\n        unchecked {\\n            if (u == 0 || u == m || m == 0)\\n                return 0;\\n            if (u > m)\\n                u = u % m;\\n\\n            int t1;\\n            int t2 = 1;\\n            uint r1 = m;\\n            uint r2 = u;\\n            uint q;\\n\\n            while (r2 != 0) {\\n                q = r1 / r2;\\n                (t1, t2, r1, r2) = (t2, t1 - int(q) * t2, r2, r1 - q * r2);\\n            }\\n\\n            if (t1 < 0)\\n                return (m - uint(-t1));\\n\\n            return uint(t1);\\n        }\\n    }\\n\\n    /**\\n     * @dev Transform affine coordinates into projective coordinates.\\n     */\\n    function toProjectivePoint(uint x0, uint y0) internal pure\\n        returns (uint[3] memory P)\\n    {\\n        P[2] = addmod(0, 1, p);\\n        P[0] = mulmod(x0, P[2], p);\\n        P[1] = mulmod(y0, P[2], p);\\n    }\\n\\n    /**\\n     * @dev Add two points in affine coordinates and return projective point.\\n     */\\n    function addAndReturnProjectivePoint(uint x1, uint y1, uint x2, uint y2) internal pure\\n        returns (uint[3] memory P)\\n    {\\n        uint x;\\n        uint y;\\n        (x, y) = add(x1, y1, x2, y2);\\n        P = toProjectivePoint(x, y);\\n    }\\n\\n    /**\\n     * @dev Transform from projective to affine coordinates.\\n     */\\n    function toAffinePoint(uint x0, uint y0, uint z0) internal pure\\n        returns (uint x1, uint y1)\\n    {\\n        uint z0Inv;\\n        z0Inv = inverseMod(z0, p);\\n        x1 = mulmod(x0, z0Inv, p);\\n        y1 = mulmod(y0, z0Inv, p);\\n    }\\n\\n    /**\\n     * @dev Return the zero curve in projective coordinates.\\n     */\\n    function zeroProj() internal pure\\n        returns (uint x, uint y, uint z)\\n    {\\n        return (0, 1, 0);\\n    }\\n\\n    /**\\n     * @dev Return the zero curve in affine coordinates.\\n     */\\n    function zeroAffine() internal pure\\n        returns (uint x, uint y)\\n    {\\n        return (0, 0);\\n    }\\n\\n    /**\\n     * @dev Check if the curve is the zero curve.\\n     */\\n    function isZeroCurve(uint x0, uint y0) internal pure\\n        returns (bool isZero)\\n    {\\n        if(x0 == 0 && y0 == 0) {\\n            return true;\\n        }\\n        return false;\\n    }\\n\\n    /**\\n     * @dev Check if a point in affine coordinates is on the curve.\\n     */\\n    function isOnCurve(uint x, uint y) internal pure\\n        returns (bool)\\n    {\\n        if (0 == x || x == p || 0 == y || y == p) {\\n            return false;\\n        }\\n\\n        uint LHS = mulmod(y, y, p); // y^2\\n        uint RHS = mulmod(mulmod(x, x, p), x, p); // x^3\\n\\n        if (a != 0) {\\n            RHS = addmod(RHS, mulmod(x, a, p), p); // x^3 + a*x\\n        }\\n        if (b != 0) {\\n            RHS = addmod(RHS, b, p); // x^3 + a*x + b\\n        }\\n\\n        return LHS == RHS;\\n    }\\n\\n    /**\\n     * @dev Double an elliptic curve point in projective coordinates. See\\n     * https://www.nayuki.io/page/elliptic-curve-point-addition-in-projective-coordinates\\n     */\\n    function twiceProj(uint x0, uint y0, uint z0) internal pure\\n        returns (uint x1, uint y1, uint z1)\\n    {\\n        uint t;\\n        uint u;\\n        uint v;\\n        uint w;\\n\\n        if(isZeroCurve(x0, y0)) {\\n            return zeroProj();\\n        }\\n\\n        u = mulmod(y0, z0, p);\\n        u = mulmod(u, 2, p);\\n\\n        v = mulmod(u, x0, p);\\n        v = mulmod(v, y0, p);\\n        v = mulmod(v, 2, p);\\n\\n        x0 = mulmod(x0, x0, p);\\n        t = mulmod(x0, 3, p);\\n\\n        z0 = mulmod(z0, z0, p);\\n        z0 = mulmod(z0, a, p);\\n        t = addmod(t, z0, p);\\n\\n        w = mulmod(t, t, p);\\n        x0 = mulmod(2, v, p);\\n        w = addmod(w, p-x0, p);\\n\\n        x0 = addmod(v, p-w, p);\\n        x0 = mulmod(t, x0, p);\\n        y0 = mulmod(y0, u, p);\\n        y0 = mulmod(y0, y0, p);\\n        y0 = mulmod(2, y0, p);\\n        y1 = addmod(x0, p-y0, p);\\n\\n        x1 = mulmod(u, w, p);\\n\\n        z1 = mulmod(u, u, p);\\n        z1 = mulmod(z1, u, p);\\n    }\\n\\n    /**\\n     * @dev Add two elliptic curve points in projective coordinates. See\\n     * https://www.nayuki.io/page/elliptic-curve-point-addition-in-projective-coordinates\\n     */\\n    function addProj(uint x0, uint y0, uint z0, uint x1, uint y1, uint z1) internal pure\\n        returns (uint x2, uint y2, uint z2)\\n    {\\n        uint t0;\\n        uint t1;\\n        uint u0;\\n        uint u1;\\n\\n        if (isZeroCurve(x0, y0)) {\\n            return (x1, y1, z1);\\n        }\\n        else if (isZeroCurve(x1, y1)) {\\n            return (x0, y0, z0);\\n        }\\n\\n        t0 = mulmod(y0, z1, p);\\n        t1 = mulmod(y1, z0, p);\\n\\n        u0 = mulmod(x0, z1, p);\\n        u1 = mulmod(x1, z0, p);\\n\\n        if (u0 == u1) {\\n            if (t0 == t1) {\\n                return twiceProj(x0, y0, z0);\\n            }\\n            else {\\n                return zeroProj();\\n            }\\n        }\\n\\n        (x2, y2, z2) = addProj2(mulmod(z0, z1, p), u0, u1, t1, t0);\\n    }\\n\\n    /**\\n     * @dev Helper function that splits addProj to avoid too many local variables.\\n     */\\n    function addProj2(uint v, uint u0, uint u1, uint t1, uint t0) private pure\\n        returns (uint x2, uint y2, uint z2)\\n    {\\n        uint u;\\n        uint u2;\\n        uint u3;\\n        uint w;\\n        uint t;\\n\\n        t = addmod(t0, p-t1, p);\\n        u = addmod(u0, p-u1, p);\\n        u2 = mulmod(u, u, p);\\n\\n        w = mulmod(t, t, p);\\n        w = mulmod(w, v, p);\\n        u1 = addmod(u1, u0, p);\\n        u1 = mulmod(u1, u2, p);\\n        w = addmod(w, p-u1, p);\\n\\n        x2 = mulmod(u, w, p);\\n\\n        u3 = mulmod(u2, u, p);\\n        u0 = mulmod(u0, u2, p);\\n        u0 = addmod(u0, p-w, p);\\n        t = mulmod(t, u0, p);\\n        t0 = mulmod(t0, u3, p);\\n\\n        y2 = addmod(t, p-t0, p);\\n\\n        z2 = mulmod(u3, v, p);\\n    }\\n\\n    /**\\n     * @dev Add two elliptic curve points in affine coordinates.\\n     */\\n    function add(uint x0, uint y0, uint x1, uint y1) internal pure\\n        returns (uint, uint)\\n    {\\n        uint z0;\\n\\n        (x0, y0, z0) = addProj(x0, y0, 1, x1, y1, 1);\\n\\n        return toAffinePoint(x0, y0, z0);\\n    }\\n\\n    /**\\n     * @dev Double an elliptic curve point in affine coordinates.\\n     */\\n    function twice(uint x0, uint y0) internal pure\\n        returns (uint, uint)\\n    {\\n        uint z0;\\n\\n        (x0, y0, z0) = twiceProj(x0, y0, 1);\\n\\n        return toAffinePoint(x0, y0, z0);\\n    }\\n\\n    /**\\n     * @dev Multiply an elliptic curve point by a 2 power base (i.e., (2^exp)*P)).\\n     */\\n    function multiplyPowerBase2(uint x0, uint y0, uint exp) internal pure\\n        returns (uint, uint)\\n    {\\n        uint base2X = x0;\\n        uint base2Y = y0;\\n        uint base2Z = 1;\\n\\n        for(uint i = 0; i < exp; i++) {\\n            (base2X, base2Y, base2Z) = twiceProj(base2X, base2Y, base2Z);\\n        }\\n\\n        return toAffinePoint(base2X, base2Y, base2Z);\\n    }\\n\\n    /**\\n     * @dev Multiply an elliptic curve point by a scalar.\\n     */\\n    function multiplyScalar(uint x0, uint y0, uint scalar) internal pure\\n        returns (uint x1, uint y1)\\n    {\\n        if(scalar == 0) {\\n            return zeroAffine();\\n        }\\n        else if (scalar == 1) {\\n            return (x0, y0);\\n        }\\n        else if (scalar == 2) {\\n            return twice(x0, y0);\\n        }\\n\\n        uint base2X = x0;\\n        uint base2Y = y0;\\n        uint base2Z = 1;\\n        uint z1 = 1;\\n        x1 = x0;\\n        y1 = y0;\\n\\n        if(scalar%2 == 0) {\\n            x1 = y1 = 0;\\n        }\\n\\n        scalar = scalar >> 1;\\n\\n        while(scalar > 0) {\\n            (base2X, base2Y, base2Z) = twiceProj(base2X, base2Y, base2Z);\\n\\n            if(scalar%2 == 1) {\\n                (x1, y1, z1) = addProj(base2X, base2Y, base2Z, x1, y1, z1);\\n            }\\n\\n            scalar = scalar >> 1;\\n        }\\n\\n        return toAffinePoint(x1, y1, z1);\\n    }\\n\\n    /**\\n     * @dev Multiply the curve's generator point by a scalar.\\n     */\\n    function multipleGeneratorByScalar(uint scalar) internal pure\\n        returns (uint, uint)\\n    {\\n        return multiplyScalar(gx, gy, scalar);\\n    }\\n\\n    /**\\n     * @dev Validate combination of message, signature, and public key.\\n     */\\n    function validateSignature(bytes32 message, uint[2] memory rs, uint[2] memory Q) internal pure\\n        returns (bool)\\n    {\\n\\n        // To disambiguate between public key solutions, include comment below.\\n        if(rs[0] == 0 || rs[0] >= n || rs[1] == 0) {// || rs[1] > lowSmax)\\n            return false;\\n        }\\n        if (!isOnCurve(Q[0], Q[1])) {\\n            return false;\\n        }\\n\\n        uint x1;\\n        uint x2;\\n        uint y1;\\n        uint y2;\\n\\n        uint sInv = inverseMod(rs[1], n);\\n        (x1, y1) = multiplyScalar(gx, gy, mulmod(uint(message), sInv, n));\\n        (x2, y2) = multiplyScalar(Q[0], Q[1], mulmod(rs[0], sInv, n));\\n        uint[3] memory P = addAndReturnProjectivePoint(x1, y1, x2, y2);\\n\\n        if (P[2] == 0) {\\n            return false;\\n        }\\n\\n        uint Px = inverseMod(P[2], p);\\n        Px = mulmod(P[0], mulmod(Px, Px, p), p);\\n\\n        return Px % n == rs[0];\\n    }\\n}\",\"keccak256\":\"0xa0dc7fe8a8877e69c22e3e2e47dbc8370027c27dbd6a22cf5d36a4c3679608c8\"},\"contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./Algorithm.sol\\\";\\nimport \\\"./EllipticCurve.sol\\\";\\nimport \\\"../BytesUtils.sol\\\";\\n\\ncontract P256SHA256Algorithm is Algorithm, EllipticCurve {\\n\\n    using BytesUtils for *;\\n\\n    /**\\n    * @dev Verifies a signature.\\n    * @param key The public key to verify with.\\n    * @param data The signed data to verify.\\n    * @param signature The signature to verify.\\n    * @return True iff the signature is valid.\\n    */\\n    function verify(bytes calldata key, bytes calldata data, bytes calldata signature) external override view returns (bool) {\\n        return validateSignature(sha256(data), parseSignature(signature), parseKey(key));\\n    }\\n\\n    function parseSignature(bytes memory data) internal pure returns (uint256[2] memory) {\\n        require(data.length == 64, \\\"Invalid p256 signature length\\\");\\n        return [uint256(data.readBytes32(0)), uint256(data.readBytes32(32))];\\n    }\\n\\n    function parseKey(bytes memory data) internal pure returns (uint256[2] memory) {\\n        require(data.length == 68, \\\"Invalid p256 key length\\\");\\n        return [uint256(data.readBytes32(4)), uint256(data.readBytes32(36))];\\n    }\\n}\\n\",\"keccak256\":\"0x60c0ee554d9a3a3f1cda75c49050143c2aaa33ade54b20d782322035baeb5f81\"}},\"version\":1}",
  "bytecode": "0x608060405234801561001057600080fd5b50611168806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610ff5565b610057565b604051901515815260200160405180910390f35b60006101316002868660405161006e92919061108b565b602060405180830381855afa15801561008b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906100ae9190610fdd565b6100ed85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061013c92505050565b61012c8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101e592505050565b61027e565b979650505050505050565b610144610f61565b81516040146101b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c69642070323536207369676e6174757265206c656e67746800000060448201526064015b60405180910390fd5b60408051808201909152806101ca846000610482565b81526020908101906101dd908590610482565b905292915050565b6101ed610f61565b8151604414610258576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c69642070323536206b6579206c656e67746800000000000000000060448201526064016101ab565b604080518082019091528061026e846004610482565b81526020016101dd846024610482565b815160009015806102b0575082517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255111155b806102bd57506020830151155b156102ca5750600061047b565b815160208301516102db91906104a6565b6102e75750600061047b565b60008080808061031e88600160200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516105cc565b905061038e7f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f57fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551848d096106b5565b885160208a01518b519398509195506103ce929091907fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551908590096106b5565b909450915060006103e186858786610782565b60408101519091506103fc576000965050505050505061047b565b600061042382600260200201516ffffffffeffffffffffffffffffffffff60601b196105cc565b90506ffffffffeffffffffffffffffffffffff60601b19808283098351098a519091506104707fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551836110ca565b149750505050505050505b9392505050565b815160009061049283602061109b565b111561049d57600080fd5b50016020015190565b60008215806104c857506ffffffffeffffffffffffffffffffffff60601b1983145b806104d1575081155b806104ef57506ffffffffeffffffffffffffffffffffff60601b1982145b156104fc575060006105c6565b60006ffffffffeffffffffffffffffffffffff60601b19838409905060006ffffffffeffffffffffffffffffffffff60601b19856ffffffffeffffffffffffffffffffffff60601b198788090990506ffffffffeffffffffffffffffffffffff60601b19807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc8709820890506ffffffffeffffffffffffffffffffffff60601b197f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b820890501490505b92915050565b60008215806105da57508183145b806105e3575081155b156105f0575060006105c6565b818311156106325781838161062e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b0692505b600060018385835b811561069057818381610676577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b94959404858102909403939192838302900391905061063a565b60008512156106a95750505050600003820390506105c6565b50929695505050505050565b600080826106ca576000805b9150915061077a565b82600114156106dd57508390508261077a565b82600214156106f0576106c185856107a8565b508390508281816001806107056002886110ca565b61071157600094508495505b600187901c96505b86156107665761072a8484846107d8565b9195509350915061073c6002886110ca565b6001141561075a57610752848484898986610acc565b919750955090505b600187901c9650610719565b610771868683610bf1565b95509550505050505b935093915050565b61078a610f7f565b60008061079987878787610c53565b90925090506101318282610c88565b60008060006107b9858560016107d8565b919650945090506107cb858583610bf1565b92509250505b9250929050565b60008060008060008060006107ed8a8a610cf3565b1561080657600060018196509650965050505050610ac3565b6ffffffffeffffffffffffffffffffffff60601b19888a0992506ffffffffeffffffffffffffffffffffff60601b196002840992506ffffffffeffffffffffffffffffffffff60601b198a840991506ffffffffeffffffffffffffffffffffff60601b1989830991506ffffffffeffffffffffffffffffffffff60601b196002830991506ffffffffeffffffffffffffffffffffff60601b198a8b0999506ffffffffeffffffffffffffffffffffff60601b1960038b0993506ffffffffeffffffffffffffffffffffff60601b1988890997506ffffffffeffffffffffffffffffffffff60601b197fffffffff00000001000000000000000000000000fffffffffffffffffffffffc890997506ffffffffeffffffffffffffffffffffff60601b1988850893506ffffffffeffffffffffffffffffffffff60601b1984850990506ffffffffeffffffffffffffffffffffff60601b198260020999506ffffffffeffffffffffffffffffffffff60601b196109958b6ffffffffeffffffffffffffffffffffff60601b196110b3565b820890506ffffffffeffffffffffffffffffffffff60601b196109cc826ffffffffeffffffffffffffffffffffff60601b196110b3565b830899506ffffffffeffffffffffffffffffffffff60601b198a850999506ffffffffeffffffffffffffffffffffff60601b19838a0998506ffffffffeffffffffffffffffffffffff60601b19898a0998506ffffffffeffffffffffffffffffffffff60601b198960020998506ffffffffeffffffffffffffffffffffff60601b19610a6c8a6ffffffffeffffffffffffffffffffffff60601b196110b3565b8b0895506ffffffffeffffffffffffffffffffffff60601b1981840996506ffffffffeffffffffffffffffffffffff60601b1983840994506ffffffffeffffffffffffffffffffffff60601b198386099450505050505b93509350939050565b6000806000806000806000610ae18d8d610cf3565b15610af85789898996509650965050505050610be5565b610b028a8a610cf3565b15610b19578c8c8c96509650965050505050610be5565b6ffffffffeffffffffffffffffffffffff60601b19888d0993506ffffffffeffffffffffffffffffffffff60601b198b8a0992506ffffffffeffffffffffffffffffffffff60601b19888e0991506ffffffffeffffffffffffffffffffffff60601b198b8b09905080821415610bb55782841415610bab57610b9c8d8d8d6107d8565b96509650965050505050610be5565b6000600181610b9c565b610bd96ffffffffeffffffffffffffffffffffff60601b19898d0983838688610d17565b91985096509450505050505b96509650969350505050565b6000806000610c14846ffffffffeffffffffffffffffffffffff60601b196105cc565b90506ffffffffeffffffffffffffffffffffff60601b1981870992506ffffffffeffffffffffffffffffffffff60601b19818609915050935093915050565b6000806000610c688787600188886001610acc565b91985096509050610c7a878783610bf1565b925092505094509492505050565b610c90610f7f565b6ffffffffeffffffffffffffffffffffff60601b196001600008604082018190526ffffffffeffffffffffffffffffffffff60601b19908409815260408101516ffffffffeffffffffffffffffffffffff60601b19908309602082015292915050565b600082158015610d01575081155b15610d0e575060016105c6565b50600092915050565b6000808080808080806ffffffffeffffffffffffffffffffffff60601b19610d538b6ffffffffeffffffffffffffffffffffff60601b196110b3565b8a0890506ffffffffeffffffffffffffffffffffff60601b19610d8a8c6ffffffffeffffffffffffffffffffffff60601b196110b3565b8d0894506ffffffffeffffffffffffffffffffffff60601b1985860993506ffffffffeffffffffffffffffffffffff60601b1981820991506ffffffffeffffffffffffffffffffffff60601b198d830991506ffffffffeffffffffffffffffffffffff60601b198c8c089a506ffffffffeffffffffffffffffffffffff60601b19848c099a506ffffffffeffffffffffffffffffffffff60601b19610e438c6ffffffffeffffffffffffffffffffffff60601b196110b3565b830891506ffffffffeffffffffffffffffffffffff60601b1982860997506ffffffffeffffffffffffffffffffffff60601b1985850992506ffffffffeffffffffffffffffffffffff60601b19848d099b506ffffffffeffffffffffffffffffffffff60601b19610ec8836ffffffffeffffffffffffffffffffffff60601b196110b3565b8d089b506ffffffffeffffffffffffffffffffffff60601b198c820990506ffffffffeffffffffffffffffffffffff60601b19838a0998506ffffffffeffffffffffffffffffffffff60601b19610f338a6ffffffffeffffffffffffffffffffffff60601b196110b3565b820896506ffffffffeffffffffffffffffffffffff60601b198d840995505050505050955095509592505050565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60008083601f840112610fae578182fd5b50813567ffffffffffffffff811115610fc5578182fd5b6020830191508360208285010111156107d157600080fd5b600060208284031215610fee578081fd5b5051919050565b6000806000806000806060878903121561100d578182fd5b863567ffffffffffffffff80821115611024578384fd5b6110308a838b01610f9d565b90985096506020890135915080821115611048578384fd5b6110548a838b01610f9d565b9096509450604089013591508082111561106c578384fd5b5061107989828a01610f9d565b979a9699509497509295939492505050565b8183823760009101908152919050565b600082198211156110ae576110ae611103565b500190565b6000828210156110c5576110c5611103565b500390565b6000826110fe577f4e487b710000000000000000000000000000000000000000000000000000000081526012600452602481fd5b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea2646970667358221220036936a4782f07c047a688a0be4b90fa9f2e8184ce2f42ccc8c65ee8fe74944664736f6c63430008040033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004361003e366004610ff5565b610057565b604051901515815260200160405180910390f35b60006101316002868660405161006e92919061108b565b602060405180830381855afa15801561008b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906100ae9190610fdd565b6100ed85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061013c92505050565b61012c8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101e592505050565b61027e565b979650505050505050565b610144610f61565b81516040146101b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c69642070323536207369676e6174757265206c656e67746800000060448201526064015b60405180910390fd5b60408051808201909152806101ca846000610482565b81526020908101906101dd908590610482565b905292915050565b6101ed610f61565b8151604414610258576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c69642070323536206b6579206c656e67746800000000000000000060448201526064016101ab565b604080518082019091528061026e846004610482565b81526020016101dd846024610482565b815160009015806102b0575082517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255111155b806102bd57506020830151155b156102ca5750600061047b565b815160208301516102db91906104a6565b6102e75750600061047b565b60008080808061031e88600160200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516105cc565b905061038e7f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f57fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551848d096106b5565b885160208a01518b519398509195506103ce929091907fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551908590096106b5565b909450915060006103e186858786610782565b60408101519091506103fc576000965050505050505061047b565b600061042382600260200201516ffffffffeffffffffffffffffffffffff60601b196105cc565b90506ffffffffeffffffffffffffffffffffff60601b19808283098351098a519091506104707fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551836110ca565b149750505050505050505b9392505050565b815160009061049283602061109b565b111561049d57600080fd5b50016020015190565b60008215806104c857506ffffffffeffffffffffffffffffffffff60601b1983145b806104d1575081155b806104ef57506ffffffffeffffffffffffffffffffffff60601b1982145b156104fc575060006105c6565b60006ffffffffeffffffffffffffffffffffff60601b19838409905060006ffffffffeffffffffffffffffffffffff60601b19856ffffffffeffffffffffffffffffffffff60601b198788090990506ffffffffeffffffffffffffffffffffff60601b19807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc8709820890506ffffffffeffffffffffffffffffffffff60601b197f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b820890501490505b92915050565b60008215806105da57508183145b806105e3575081155b156105f0575060006105c6565b818311156106325781838161062e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b0692505b600060018385835b811561069057818381610676577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b94959404858102909403939192838302900391905061063a565b60008512156106a95750505050600003820390506105c6565b50929695505050505050565b600080826106ca576000805b9150915061077a565b82600114156106dd57508390508261077a565b82600214156106f0576106c185856107a8565b508390508281816001806107056002886110ca565b61071157600094508495505b600187901c96505b86156107665761072a8484846107d8565b9195509350915061073c6002886110ca565b6001141561075a57610752848484898986610acc565b919750955090505b600187901c9650610719565b610771868683610bf1565b95509550505050505b935093915050565b61078a610f7f565b60008061079987878787610c53565b90925090506101318282610c88565b60008060006107b9858560016107d8565b919650945090506107cb858583610bf1565b92509250505b9250929050565b60008060008060008060006107ed8a8a610cf3565b1561080657600060018196509650965050505050610ac3565b6ffffffffeffffffffffffffffffffffff60601b19888a0992506ffffffffeffffffffffffffffffffffff60601b196002840992506ffffffffeffffffffffffffffffffffff60601b198a840991506ffffffffeffffffffffffffffffffffff60601b1989830991506ffffffffeffffffffffffffffffffffff60601b196002830991506ffffffffeffffffffffffffffffffffff60601b198a8b0999506ffffffffeffffffffffffffffffffffff60601b1960038b0993506ffffffffeffffffffffffffffffffffff60601b1988890997506ffffffffeffffffffffffffffffffffff60601b197fffffffff00000001000000000000000000000000fffffffffffffffffffffffc890997506ffffffffeffffffffffffffffffffffff60601b1988850893506ffffffffeffffffffffffffffffffffff60601b1984850990506ffffffffeffffffffffffffffffffffff60601b198260020999506ffffffffeffffffffffffffffffffffff60601b196109958b6ffffffffeffffffffffffffffffffffff60601b196110b3565b820890506ffffffffeffffffffffffffffffffffff60601b196109cc826ffffffffeffffffffffffffffffffffff60601b196110b3565b830899506ffffffffeffffffffffffffffffffffff60601b198a850999506ffffffffeffffffffffffffffffffffff60601b19838a0998506ffffffffeffffffffffffffffffffffff60601b19898a0998506ffffffffeffffffffffffffffffffffff60601b198960020998506ffffffffeffffffffffffffffffffffff60601b19610a6c8a6ffffffffeffffffffffffffffffffffff60601b196110b3565b8b0895506ffffffffeffffffffffffffffffffffff60601b1981840996506ffffffffeffffffffffffffffffffffff60601b1983840994506ffffffffeffffffffffffffffffffffff60601b198386099450505050505b93509350939050565b6000806000806000806000610ae18d8d610cf3565b15610af85789898996509650965050505050610be5565b610b028a8a610cf3565b15610b19578c8c8c96509650965050505050610be5565b6ffffffffeffffffffffffffffffffffff60601b19888d0993506ffffffffeffffffffffffffffffffffff60601b198b8a0992506ffffffffeffffffffffffffffffffffff60601b19888e0991506ffffffffeffffffffffffffffffffffff60601b198b8b09905080821415610bb55782841415610bab57610b9c8d8d8d6107d8565b96509650965050505050610be5565b6000600181610b9c565b610bd96ffffffffeffffffffffffffffffffffff60601b19898d0983838688610d17565b91985096509450505050505b96509650969350505050565b6000806000610c14846ffffffffeffffffffffffffffffffffff60601b196105cc565b90506ffffffffeffffffffffffffffffffffff60601b1981870992506ffffffffeffffffffffffffffffffffff60601b19818609915050935093915050565b6000806000610c688787600188886001610acc565b91985096509050610c7a878783610bf1565b925092505094509492505050565b610c90610f7f565b6ffffffffeffffffffffffffffffffffff60601b196001600008604082018190526ffffffffeffffffffffffffffffffffff60601b19908409815260408101516ffffffffeffffffffffffffffffffffff60601b19908309602082015292915050565b600082158015610d01575081155b15610d0e575060016105c6565b50600092915050565b6000808080808080806ffffffffeffffffffffffffffffffffff60601b19610d538b6ffffffffeffffffffffffffffffffffff60601b196110b3565b8a0890506ffffffffeffffffffffffffffffffffff60601b19610d8a8c6ffffffffeffffffffffffffffffffffff60601b196110b3565b8d0894506ffffffffeffffffffffffffffffffffff60601b1985860993506ffffffffeffffffffffffffffffffffff60601b1981820991506ffffffffeffffffffffffffffffffffff60601b198d830991506ffffffffeffffffffffffffffffffffff60601b198c8c089a506ffffffffeffffffffffffffffffffffff60601b19848c099a506ffffffffeffffffffffffffffffffffff60601b19610e438c6ffffffffeffffffffffffffffffffffff60601b196110b3565b830891506ffffffffeffffffffffffffffffffffff60601b1982860997506ffffffffeffffffffffffffffffffffff60601b1985850992506ffffffffeffffffffffffffffffffffff60601b19848d099b506ffffffffeffffffffffffffffffffffff60601b19610ec8836ffffffffeffffffffffffffffffffffff60601b196110b3565b8d089b506ffffffffeffffffffffffffffffffffff60601b198c820990506ffffffffeffffffffffffffffffffffff60601b19838a0998506ffffffffeffffffffffffffffffffffff60601b19610f338a6ffffffffeffffffffffffffffffffffff60601b196110b3565b820896506ffffffffeffffffffffffffffffffffff60601b198d840995505050505050955095509592505050565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60008083601f840112610fae578182fd5b50813567ffffffffffffffff811115610fc5578182fd5b6020830191508360208285010111156107d157600080fd5b600060208284031215610fee578081fd5b5051919050565b6000806000806000806060878903121561100d578182fd5b863567ffffffffffffffff80821115611024578384fd5b6110308a838b01610f9d565b90985096506020890135915080821115611048578384fd5b6110548a838b01610f9d565b9096509450604089013591508082111561106c578384fd5b5061107989828a01610f9d565b979a9699509497509295939492505050565b8183823760009101908152919050565b600082198211156110ae576110ae611103565b500190565b6000828210156110c5576110c5611103565b500390565b6000826110fe577f4e487b710000000000000000000000000000000000000000000000000000000081526012600452602481fd5b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea2646970667358221220036936a4782f07c047a688a0be4b90fa9f2e8184ce2f42ccc8c65ee8fe74944664736f6c63430008040033",
  "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
  }
}