{
  "address": "0x5e5a01e17Ff2f49a84d8374A4034460d82AD9107",
  "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": "0xd570bab21d40dcc343b857fc21e0c4f8d48c43bbffe0dfbfbdbd50cfb6cc59be",
  "receipt": {
    "to": null,
    "from": "0xa303ddC620aa7d1390BACcc8A495508B183fab59",
    "contractAddress": "0x5e5a01e17Ff2f49a84d8374A4034460d82AD9107",
    "transactionIndex": 8,
    "gasUsed": "2240436",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0xa5c77d62b7010196a5aa03e58891177c5a3097c4df363d253029417f6b8ec7a6",
    "transactionHash": "0xd570bab21d40dcc343b857fc21e0c4f8d48c43bbffe0dfbfbdbd50cfb6cc59be",
    "logs": [],
    "blockNumber": 10645995,
    "cumulativeGasUsed": "2531328",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "solcInputHash": "424cfdf012b9aa11d2e839569d49524c",
  "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\":false,\"runs\":200},\"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": "0x608060405234801561001057600080fd5b50612850806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004a600480360381019061004591906124bb565b610060565b60405161005791906125f2565b60405180910390f35b6000610156600286866040516100779291906125d9565b602060405180830381855afa158015610094573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906100b79190612492565b61010485858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610162565b6101518a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506101f6565b61028a565b90509695505050505050565b61016a6123ef565b60408251146101ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101a59061262d565b60405180910390fd5b60405180604001604052806101cd6000856108a190919063ffffffff16565b60001c81526020016101e96020856108a190919063ffffffff16565b60001c8152509050919050565b6101fe6123ef565b6044825114610242576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102399061260d565b60405180910390fd5b60405180604001604052806102616004856108a190919063ffffffff16565b60001c815260200161027d6024856108a190919063ffffffff16565b60001c8152509050919050565b600080836000600281106102c7577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020151148061033657507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518360006002811061032e577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015110155b8061037f5750600083600160028110610378577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020151145b1561038d576000905061089a565b610413826000600281106103ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015183600160028110610409577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201516108cc565b610420576000905061089a565b600080600080600061049088600160028110610465577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551610bf9565b90506105377f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f57fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518061052c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b848d60001c09610d03565b809450819650505061065b8760006002811061057c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020151886001600281106105bb577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255180610615577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b848c600060028110610650577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015109610d03565b8093508195505050600061067186858786610e09565b90506000816002600381106106af577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015114156106c9576000965050505050505061089a565b600061073382600260038110610708577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201517fffffffff00000001000000000000000000000000ffffffffffffffffffffffff610bf9565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061078a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806107df577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8283098360006003811061081c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201510990508960006002811061085e577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518261088f9190612722565b149750505050505050505b9392505050565b600082516020836108b29190612669565b11156108bd57600080fd5b81602084010151905092915050565b600082600014806108fc57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806109075750816000145b8061093157507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b1561093f5760009050610bf3565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610996577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806109f2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610a48577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b87880909905060007fffffffff00000001000000000000000000000000fffffffffffffffffffffffc14610b48577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610acb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610b20577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffff00000001000000000000000000000000fffffffffffffffffffffffc8709820890505b60007f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b14610beb577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610bc5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b820890505b808214925050505b92915050565b600080831480610c0857508183145b80610c135750600082145b15610c215760009050610cfd565b81831115610c6357818381610c5f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b0692505b600080600190506000849050600086905060005b60008214610cd957818381610cb5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b04905083848202860383848402860380955081965082975083985050505050610c77565b6000851215610cf45784600003870395505050505050610cfd565b84955050505050505b92915050565b6000806000831415610d2057610d17610e3e565b91509150610e01565b6001831415610d3457848491509150610e01565b6002831415610d5057610d478585610e4c565b91509150610e01565b600085905060008590506000600190506000600190508895508794506000600288610d7b9190612722565b1415610d8957600094508495505b600187901c96505b6000871115610ded57610da5848484610e80565b8094508195508296505050506001600288610dc09190612722565b1415610de157610dd4848484898986611721565b8093508197508298505050505b600187901c9650610d91565b610df8868683611998565b95509550505050505b935093915050565b610e11612411565b600080610e2087878787611a86565b8092508193505050610e328282611ac0565b92505050949350505050565b600080600080915091509091565b6000806000610e5d85856001610e80565b809350819650829750505050610e74858583611998565b92509250509250929050565b6000806000806000806000610e958a8a611d1d565b15610eb157610ea2611d47565b96509650965050505050611718565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610f06577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b888a0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610f60577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6002840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610fbb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8a840991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611015577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b89830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061106f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6002830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806110ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8a8b0999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611124577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60038b0993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061117f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b88890997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806111d9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffff00000001000000000000000000000000fffffffffffffffffffffffc890997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611253577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b88850893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806112ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b84850990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611307577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8260020999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611362577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff61138e91906126bf565b820890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806113e7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b817fffffffff00000001000000000000000000000000ffffffffffffffffffffffff61141391906126bf565b830899507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061146c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8a850999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806114c6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b838a0998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611520577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b898a0998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061157a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8960020998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806115d5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff61160191906126bf565b8b0895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061165a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81840996507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806116b4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b83840994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061170e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8386099450505050505b93509350939050565b60008060008060008060006117368d8d611d1d565b1561174d578989899650965096505050505061198c565b6117578a8a611d1d565b1561176e578c8c8c9650965096505050505061198c565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806117c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b888d0993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061181d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8b8a0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611877577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b888e0991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806118d1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8b8b099050808214156119175782841415611900576118f18d8d8d610e80565b9650965096505050505061198c565b611908611d47565b9650965096505050505061198c565b61197b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061196f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b898d0983838688611d5c565b809750819850829950505050505050505b96509650969350505050565b60008060006119c7847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff610bf9565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611a1e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81870992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611a78577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b818609915050935093915050565b6000806000611a9b8787600188886001611721565b809350819850829950505050611ab2878783611998565b925092505094509492505050565b611ac8612411565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611b1d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600160000881600260038110611b5c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611bba577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81600260038110611bf4577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020151840981600060038110611c35577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611c93577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81600260038110611ccd577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020151830981600160038110611d0e577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201818152505092915050565b60008083148015611d2e5750600082145b15611d3c5760019050611d41565b600090505b92915050565b60008060008060016000925092509250909192565b6000806000806000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611dbd577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff611de991906126bf565b8a0890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611e42577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff611e6e91906126bf565b8d0894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611ec7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611f21577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611f7b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8d830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611fd5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8c8c089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061202f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b848c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80612089577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6120b591906126bf565b830891507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061210e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b82860997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80612168577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b85850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806121c2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b848d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061221c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b827fffffffff00000001000000000000000000000000ffffffffffffffffffffffff61224891906126bf565b8d089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806122a1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8c820990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806122fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b838a0998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80612355577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff61238191906126bf565b820896507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806123da577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8d840995505050505050955095509592505050565b6040518060400160405280600290602082028036833780820191505090505090565b6040518060600160405280600390602082028036833780820191505090505090565b60008151905061244281612803565b92915050565b60008083601f84011261245a57600080fd5b8235905067ffffffffffffffff81111561247357600080fd5b60208301915083600182028301111561248b57600080fd5b9250929050565b6000602082840312156124a457600080fd5b60006124b284828501612433565b91505092915050565b600080600080600080606087890312156124d457600080fd5b600087013567ffffffffffffffff8111156124ee57600080fd5b6124fa89828a01612448565b9650965050602087013567ffffffffffffffff81111561251957600080fd5b61252589828a01612448565b9450945050604087013567ffffffffffffffff81111561254457600080fd5b61255089828a01612448565b92509250509295509295509295565b612568816126f3565b82525050565b600061257a838561264d565b9350612587838584612713565b82840190509392505050565b60006125a0601783612658565b91506125ab826127b1565b602082019050919050565b60006125c3601d83612658565b91506125ce826127da565b602082019050919050565b60006125e682848661256e565b91508190509392505050565b6000602082019050612607600083018461255f565b92915050565b6000602082019050818103600083015261262681612593565b9050919050565b60006020820190508181036000830152612646816125b6565b9050919050565b600081905092915050565b600082825260208201905092915050565b600061267482612709565b915061267f83612709565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156126b4576126b3612753565b5b828201905092915050565b60006126ca82612709565b91506126d583612709565b9250828210156126e8576126e7612753565b5b828203905092915050565b60008115159050919050565b6000819050919050565b6000819050919050565b82818337600083830152505050565b600061272d82612709565b915061273883612709565b92508261274857612747612782565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f496e76616c69642070323536206b6579206c656e677468000000000000000000600082015250565b7f496e76616c69642070323536207369676e6174757265206c656e677468000000600082015250565b61280c816126ff565b811461281757600080fd5b5056fea264697066735822122041b469a58c17efa4bbf76a90284953a55d4d07789c01f010594180f826f9babe64736f6c63430008040033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063de8f50a114610030575b600080fd5b61004a600480360381019061004591906124bb565b610060565b60405161005791906125f2565b60405180910390f35b6000610156600286866040516100779291906125d9565b602060405180830381855afa158015610094573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906100b79190612492565b61010485858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610162565b6101518a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506101f6565b61028a565b90509695505050505050565b61016a6123ef565b60408251146101ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101a59061262d565b60405180910390fd5b60405180604001604052806101cd6000856108a190919063ffffffff16565b60001c81526020016101e96020856108a190919063ffffffff16565b60001c8152509050919050565b6101fe6123ef565b6044825114610242576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102399061260d565b60405180910390fd5b60405180604001604052806102616004856108a190919063ffffffff16565b60001c815260200161027d6024856108a190919063ffffffff16565b60001c8152509050919050565b600080836000600281106102c7577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020151148061033657507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518360006002811061032e577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015110155b8061037f5750600083600160028110610378577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020151145b1561038d576000905061089a565b610413826000600281106103ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015183600160028110610409577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201516108cc565b610420576000905061089a565b600080600080600061049088600160028110610465577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551610bf9565b90506105377f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f57fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518061052c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b848d60001c09610d03565b809450819650505061065b8760006002811061057c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020151886001600281106105bb577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255180610615577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b848c600060028110610650577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015109610d03565b8093508195505050600061067186858786610e09565b90506000816002600381106106af577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015114156106c9576000965050505050505061089a565b600061073382600260038110610708577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201517fffffffff00000001000000000000000000000000ffffffffffffffffffffffff610bf9565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061078a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806107df577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8283098360006003811061081c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201510990508960006002811061085e577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201517fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518261088f9190612722565b149750505050505050505b9392505050565b600082516020836108b29190612669565b11156108bd57600080fd5b81602084010151905092915050565b600082600014806108fc57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806109075750816000145b8061093157507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b1561093f5760009050610bf3565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610996577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806109f2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610a48577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b87880909905060007fffffffff00000001000000000000000000000000fffffffffffffffffffffffc14610b48577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610acb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610b20577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffff00000001000000000000000000000000fffffffffffffffffffffffc8709820890505b60007f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b14610beb577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610bc5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b820890505b808214925050505b92915050565b600080831480610c0857508183145b80610c135750600082145b15610c215760009050610cfd565b81831115610c6357818381610c5f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b0692505b600080600190506000849050600086905060005b60008214610cd957818381610cb5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b04905083848202860383848402860380955081965082975083985050505050610c77565b6000851215610cf45784600003870395505050505050610cfd565b84955050505050505b92915050565b6000806000831415610d2057610d17610e3e565b91509150610e01565b6001831415610d3457848491509150610e01565b6002831415610d5057610d478585610e4c565b91509150610e01565b600085905060008590506000600190506000600190508895508794506000600288610d7b9190612722565b1415610d8957600094508495505b600187901c96505b6000871115610ded57610da5848484610e80565b8094508195508296505050506001600288610dc09190612722565b1415610de157610dd4848484898986611721565b8093508197508298505050505b600187901c9650610d91565b610df8868683611998565b95509550505050505b935093915050565b610e11612411565b600080610e2087878787611a86565b8092508193505050610e328282611ac0565b92505050949350505050565b600080600080915091509091565b6000806000610e5d85856001610e80565b809350819650829750505050610e74858583611998565b92509250509250929050565b6000806000806000806000610e958a8a611d1d565b15610eb157610ea2611d47565b96509650965050505050611718565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610f06577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b888a0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610f60577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6002840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80610fbb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8a840991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611015577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b89830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061106f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6002830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806110ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8a8b0999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611124577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60038b0993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061117f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b88890997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806111d9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffff00000001000000000000000000000000fffffffffffffffffffffffc890997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611253577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b88850893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806112ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b84850990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611307577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8260020999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611362577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff61138e91906126bf565b820890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806113e7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b817fffffffff00000001000000000000000000000000ffffffffffffffffffffffff61141391906126bf565b830899507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061146c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8a850999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806114c6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b838a0998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611520577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b898a0998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061157a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8960020998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806115d5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff61160191906126bf565b8b0895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061165a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81840996507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806116b4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b83840994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061170e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8386099450505050505b93509350939050565b60008060008060008060006117368d8d611d1d565b1561174d578989899650965096505050505061198c565b6117578a8a611d1d565b1561176e578c8c8c9650965096505050505061198c565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806117c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b888d0993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061181d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8b8a0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611877577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b888e0991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806118d1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8b8b099050808214156119175782841415611900576118f18d8d8d610e80565b9650965096505050505061198c565b611908611d47565b9650965096505050505061198c565b61197b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061196f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b898d0983838688611d5c565b809750819850829950505050505050505b96509650969350505050565b60008060006119c7847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff610bf9565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611a1e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81870992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611a78577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b818609915050935093915050565b6000806000611a9b8787600188886001611721565b809350819850829950505050611ab2878783611998565b925092505094509492505050565b611ac8612411565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611b1d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600160000881600260038110611b5c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611bba577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81600260038110611bf4577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020151840981600060038110611c35577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611c93577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81600260038110611ccd577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020151830981600160038110611d0e577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201818152505092915050565b60008083148015611d2e5750600082145b15611d3c5760019050611d41565b600090505b92915050565b60008060008060016000925092509250909192565b6000806000806000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611dbd577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff611de991906126bf565b8a0890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611e42577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff611e6e91906126bf565b8d0894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611ec7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611f21577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611f7b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8d830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80611fd5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8c8c089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061202f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b848c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80612089577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6120b591906126bf565b830891507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061210e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b82860997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80612168577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b85850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806121c2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b848d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8061221c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b827fffffffff00000001000000000000000000000000ffffffffffffffffffffffff61224891906126bf565b8d089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806122a1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8c820990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806122fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b838a0998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80612355577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff61238191906126bf565b820896507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff806123da577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8d840995505050505050955095509592505050565b6040518060400160405280600290602082028036833780820191505090505090565b6040518060600160405280600390602082028036833780820191505090505090565b60008151905061244281612803565b92915050565b60008083601f84011261245a57600080fd5b8235905067ffffffffffffffff81111561247357600080fd5b60208301915083600182028301111561248b57600080fd5b9250929050565b6000602082840312156124a457600080fd5b60006124b284828501612433565b91505092915050565b600080600080600080606087890312156124d457600080fd5b600087013567ffffffffffffffff8111156124ee57600080fd5b6124fa89828a01612448565b9650965050602087013567ffffffffffffffff81111561251957600080fd5b61252589828a01612448565b9450945050604087013567ffffffffffffffff81111561254457600080fd5b61255089828a01612448565b92509250509295509295509295565b612568816126f3565b82525050565b600061257a838561264d565b9350612587838584612713565b82840190509392505050565b60006125a0601783612658565b91506125ab826127b1565b602082019050919050565b60006125c3601d83612658565b91506125ce826127da565b602082019050919050565b60006125e682848661256e565b91508190509392505050565b6000602082019050612607600083018461255f565b92915050565b6000602082019050818103600083015261262681612593565b9050919050565b60006020820190508181036000830152612646816125b6565b9050919050565b600081905092915050565b600082825260208201905092915050565b600061267482612709565b915061267f83612709565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156126b4576126b3612753565b5b828201905092915050565b60006126ca82612709565b91506126d583612709565b9250828210156126e8576126e7612753565b5b828203905092915050565b60008115159050919050565b6000819050919050565b6000819050919050565b82818337600083830152505050565b600061272d82612709565b915061273883612709565b92508261274857612747612782565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f496e76616c69642070323536206b6579206c656e677468000000000000000000600082015250565b7f496e76616c69642070323536207369676e6174757265206c656e677468000000600082015250565b61280c816126ff565b811461281757600080fd5b5056fea264697066735822122041b469a58c17efa4bbf76a90284953a55d4d07789c01f010594180f826f9babe64736f6c63430008040033",
  "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
  }
}