Contract
0x8c7382f9d8f56b33781fe506e897a4f1e2d17255
4
Contract Overview
Balance:
0 MATIC
Token:
My Name Tag:
Not Available
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
VRFCoordinator
Compiler Version
v0.6.6+commit.6c089d02
Contract Source Code (Solidity)
/** *Submitted for verification at polygonscan.com on 2021-07-26 */ /** *Submitted for verification at Etherscan.io on 2020-08-26 */ // File: contracts/vendor/SafeMath.sol pragma solidity ^0.6.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, "SafeMath: modulo by zero"); return a % b; } } // File: contracts/interfaces/LinkTokenInterface.sol pragma solidity ^0.6.0; interface LinkTokenInterface { function allowance(address owner, address spender) external view returns (uint256 remaining); function approve(address spender, uint256 value) external returns (bool success); function balanceOf(address owner) external view returns (uint256 balance); function decimals() external view returns (uint8 decimalPlaces); function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); function increaseApproval(address spender, uint256 subtractedValue) external; function name() external view returns (string memory tokenName); function symbol() external view returns (string memory tokenSymbol); function totalSupply() external view returns (uint256 totalTokensIssued); function transfer(address to, uint256 value) external returns (bool success); function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success); function transferFrom(address from, address to, uint256 value) external returns (bool success); } // File: contracts/interfaces/BlockHashStoreInterface.sol pragma solidity 0.6.6; interface BlockHashStoreInterface { function getBlockhash(uint256 number) external view returns (bytes32); } // File: contracts/VRF.sol pragma solidity 0.6.6; /** **************************************************************************** * @notice Verification of verifiable-random-function (VRF) proofs, following * @notice https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 * @notice See https://eprint.iacr.org/2017/099.pdf for security proofs. * @dev Bibliographic references: * @dev Goldberg, et al., "Verifiable Random Functions (VRFs)", Internet Draft * @dev draft-irtf-cfrg-vrf-05, IETF, Aug 11 2019, * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05 * @dev Papadopoulos, et al., "Making NSEC5 Practical for DNSSEC", Cryptology * @dev ePrint Archive, Report 2017/099, https://eprint.iacr.org/2017/099.pdf * **************************************************************************** * @dev USAGE * @dev The main entry point is randomValueFromVRFProof. See its docstring. * **************************************************************************** * @dev PURPOSE * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is computationally indistinguishable to her from a uniform * @dev random sample from the output space. * @dev The purpose of this contract is to perform that verification. * **************************************************************************** * @dev DESIGN NOTES * @dev The VRF algorithm verified here satisfies the full unqiqueness, full * @dev collision resistance, and full pseudorandomness security properties. * @dev See "SECURITY PROPERTIES" below, and * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-3 * @dev An elliptic curve point is generally represented in the solidity code * @dev as a uint256[2], corresponding to its affine coordinates in * @dev GF(FIELD_SIZE). * @dev For the sake of efficiency, this implementation deviates from the spec * @dev in some minor ways: * @dev - Keccak hash rather than the SHA256 hash recommended in * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 * @dev Keccak costs much less gas on the EVM, and provides similar security. * @dev - Secp256k1 curve instead of the P-256 or ED25519 curves recommended in * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 * @dev For curve-point multiplication, it's much cheaper to abuse ECRECOVER * @dev - hashToCurve recursively hashes until it finds a curve x-ordinate. On * @dev the EVM, this is slightly more efficient than the recommendation in * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 * @dev step 5, to concatenate with a nonce then hash, and rehash with the * @dev nonce updated until a valid x-ordinate is found. * @dev - hashToCurve does not include a cipher version string or the byte 0x1 * @dev in the hash message, as recommended in step 5.B of the draft * @dev standard. They are unnecessary here because no variation in the * @dev cipher suite is allowed. * @dev - Similarly, the hash input in scalarFromCurvePoints does not include a * @dev commitment to the cipher suite, either, which differs from step 2 of * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 * @dev . Also, the hash input is the concatenation of the uncompressed * @dev points, not the compressed points as recommended in step 3. * @dev - In the calculation of the challenge value "c", the "u" value (i.e. * @dev the value computed by Reggie as the nonce times the secp256k1 * @dev generator point, see steps 5 and 7 of * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 * @dev ) is replaced by its ethereum address, i.e. the lower 160 bits of the * @dev keccak hash of the original u. This is because we only verify the * @dev calculation of u up to its address, by abusing ECRECOVER. * **************************************************************************** * @dev SECURITY PROPERTIES * @dev Here are the security properties for this VRF: * @dev Full uniqueness: For any seed and valid VRF public key, there is * @dev exactly one VRF output which can be proved to come from that seed, in * @dev the sense that the proof will pass verifyVRFProof. * @dev Full collision resistance: It's cryptographically infeasible to find * @dev two seeds with same VRF output from a fixed, valid VRF key * @dev Full pseudorandomness: Absent the proofs that the VRF outputs are * @dev derived from a given seed, the outputs are computationally * @dev indistinguishable from randomness. * @dev https://eprint.iacr.org/2017/099.pdf, Appendix B contains the proofs * @dev for these properties. * @dev For secp256k1, the key validation described in section * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.6 * @dev is unnecessary, because secp256k1 has cofactor 1, and the * @dev representation of the public key used here (affine x- and y-ordinates * @dev of the secp256k1 point on the standard y^2=x^3+7 curve) cannot refer to * @dev the point at infinity. * **************************************************************************** * @dev OTHER SECURITY CONSIDERATIONS * * @dev The seed input to the VRF could in principle force an arbitrary amount * @dev of work in hashToCurve, by requiring extra rounds of hashing and * @dev checking whether that's yielded the x ordinate of a secp256k1 point. * @dev However, under the Random Oracle Model the probability of choosing a * @dev point which forces n extra rounds in hashToCurve is 2⁻ⁿ. The base cost * @dev for calling hashToCurve is about 25,000 gas, and each round of checking * @dev for a valid x ordinate costs about 15,555 gas, so to find a seed for * @dev which hashToCurve would cost more than 2,017,000 gas, one would have to * @dev try, in expectation, about 2¹²⁸ seeds, which is infeasible for any * @dev foreseeable computational resources. (25,000 + 128 * 15,555 < 2,017,000.) * @dev Since the gas block limit for the Ethereum main net is 10,000,000 gas, * @dev this means it is infeasible for an adversary to prevent correct * @dev operation of this contract by choosing an adverse seed. * @dev (See TestMeasureHashToCurveGasCost for verification of the gas cost for * @dev hashToCurve.) * @dev It may be possible to make a secure constant-time hashToCurve function. * @dev See notes in hashToCurve docstring. */ contract VRF { // See https://www.secg.org/sec2-v2.pdf, section 2.4.1, for these constants. uint256 constant private GROUP_ORDER = // Number of points in Secp256k1 // solium-disable-next-line indentation 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; // Prime characteristic of the galois field over which Secp256k1 is defined uint256 constant private FIELD_SIZE = // solium-disable-next-line indentation 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; uint256 constant private WORD_LENGTH_BYTES = 0x20; // (base^exponent) % FIELD_SIZE // Cribbed from https://medium.com/@rbkhmrcr/precompiles-solidity-e5d29bd428c4 function bigModExp(uint256 base, uint256 exponent) internal view returns (uint256 exponentiation) { uint256 callResult; uint256[6] memory bigModExpContractInputs; bigModExpContractInputs[0] = WORD_LENGTH_BYTES; // Length of base bigModExpContractInputs[1] = WORD_LENGTH_BYTES; // Length of exponent bigModExpContractInputs[2] = WORD_LENGTH_BYTES; // Length of modulus bigModExpContractInputs[3] = base; bigModExpContractInputs[4] = exponent; bigModExpContractInputs[5] = FIELD_SIZE; uint256[1] memory output; assembly { // solhint-disable-line no-inline-assembly callResult := staticcall( not(0), // Gas cost: no limit 0x05, // Bigmodexp contract address bigModExpContractInputs, 0xc0, // Length of input segment: 6*0x20-bytes output, 0x20 // Length of output segment ) } if (callResult == 0) {revert("bigModExp failure!");} return output[0]; } // Let q=FIELD_SIZE. q % 4 = 3, ∴ x≡r^2 mod q ⇒ x^SQRT_POWER≡±r mod q. See // https://en.wikipedia.org/wiki/Modular_square_root#Prime_or_prime_power_modulus uint256 constant private SQRT_POWER = (FIELD_SIZE + 1) >> 2; // Computes a s.t. a^2 = x in the field. Assumes a exists function squareRoot(uint256 x) internal view returns (uint256) { return bigModExp(x, SQRT_POWER); } // The value of y^2 given that (x,y) is on secp256k1. function ySquared(uint256 x) internal pure returns (uint256) { // Curve is y^2=x^3+7. See section 2.4.1 of https://www.secg.org/sec2-v2.pdf uint256 xCubed = mulmod(x, mulmod(x, x, FIELD_SIZE), FIELD_SIZE); return addmod(xCubed, 7, FIELD_SIZE); } // True iff p is on secp256k1 function isOnCurve(uint256[2] memory p) internal pure returns (bool) { return ySquared(p[0]) == mulmod(p[1], p[1], FIELD_SIZE); } // Hash x uniformly into {0, ..., FIELD_SIZE-1}. function fieldHash(bytes memory b) internal pure returns (uint256 x_) { x_ = uint256(keccak256(b)); // Rejecting if x >= FIELD_SIZE corresponds to step 2.1 in section 2.3.4 of // http://www.secg.org/sec1-v2.pdf , which is part of the definition of // string_to_point in the IETF draft while (x_ >= FIELD_SIZE) { x_ = uint256(keccak256(abi.encodePacked(x_))); } } // Hash b to a random point which hopefully lies on secp256k1. The y ordinate // is always even, due to // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 // step 5.C, which references arbitrary_string_to_point, defined in // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 as // returning the point with given x ordinate, and even y ordinate. function newCandidateSecp256k1Point(bytes memory b) internal view returns (uint256[2] memory p) { p[0] = fieldHash(b); p[1] = squareRoot(ySquared(p[0])); if (p[1] % 2 == 1) { p[1] = FIELD_SIZE - p[1]; } } // Domain-separation tag for initial hash in hashToCurve. Corresponds to // vrf.go/hashToCurveHashPrefix uint256 constant HASH_TO_CURVE_HASH_PREFIX = 1; // Cryptographic hash function onto the curve. // // Corresponds to algorithm in section 5.4.1.1 of the draft standard. (But see // DESIGN NOTES above for slight differences.) // // TODO(alx): Implement a bounded-computation hash-to-curve, as described in // "Construction of Rational Points on Elliptic Curves over Finite Fields" // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.831.5299&rep=rep1&type=pdf // and suggested by // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-01#section-5.2.2 // (Though we can't used exactly that because secp256k1's j-invariant is 0.) // // This would greatly simplify the analysis in "OTHER SECURITY CONSIDERATIONS" // https://www.pivotaltracker.com/story/show/171120900 function hashToCurve(uint256[2] memory pk, uint256 input) internal view returns (uint256[2] memory rv) { rv = newCandidateSecp256k1Point(abi.encodePacked(HASH_TO_CURVE_HASH_PREFIX, pk, input)); while (!isOnCurve(rv)) { rv = newCandidateSecp256k1Point(abi.encodePacked(rv[0])); } } /** ********************************************************************* * @notice Check that product==scalar*multiplicand * * @dev Based on Vitalik Buterin's idea in ethresear.ch post cited below. * * @param multiplicand: secp256k1 point * @param scalar: non-zero GF(GROUP_ORDER) scalar * @param product: secp256k1 expected to be multiplier * multiplicand * @return verifies true iff product==scalar*multiplicand, with cryptographically high probability */ function ecmulVerify(uint256[2] memory multiplicand, uint256 scalar, uint256[2] memory product) internal pure returns(bool verifies) { require(scalar != 0); // Rules out an ecrecover failure case uint256 x = multiplicand[0]; // x ordinate of multiplicand uint8 v = multiplicand[1] % 2 == 0 ? 27 : 28; // parity of y ordinate // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 // Point corresponding to address ecrecover(0, v, x, s=scalar*x) is // (x⁻¹ mod GROUP_ORDER) * (scalar * x * multiplicand - 0 * g), i.e. // scalar*multiplicand. See https://crypto.stackexchange.com/a/18106 bytes32 scalarTimesX = bytes32(mulmod(scalar, x, GROUP_ORDER)); address actual = ecrecover(bytes32(0), v, bytes32(x), scalarTimesX); // Explicit conversion to address takes bottom 160 bits address expected = address(uint256(keccak256(abi.encodePacked(product)))); return (actual == expected); } // Returns x1/z1-x2/z2=(x1z2-x2z1)/(z1z2) in projective coordinates on P¹(𝔽ₙ) function projectiveSub(uint256 x1, uint256 z1, uint256 x2, uint256 z2) internal pure returns(uint256 x3, uint256 z3) { uint256 num1 = mulmod(z2, x1, FIELD_SIZE); uint256 num2 = mulmod(FIELD_SIZE - x2, z1, FIELD_SIZE); (x3, z3) = (addmod(num1, num2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); } // Returns x1/z1*x2/z2=(x1x2)/(z1z2), in projective coordinates on P¹(𝔽ₙ) function projectiveMul(uint256 x1, uint256 z1, uint256 x2, uint256 z2) internal pure returns(uint256 x3, uint256 z3) { (x3, z3) = (mulmod(x1, x2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); } /** ************************************************************************** @notice Computes elliptic-curve sum, in projective co-ordinates @dev Using projective coordinates avoids costly divisions @dev To use this with p and q in affine coordinates, call @dev projectiveECAdd(px, py, qx, qy). This will return @dev the addition of (px, py, 1) and (qx, qy, 1), in the @dev secp256k1 group. @dev This can be used to calculate the z which is the inverse to zInv @dev in isValidVRFOutput. But consider using a faster @dev re-implementation such as ProjectiveECAdd in the golang vrf package. @dev This function assumes [px,py,1],[qx,qy,1] are valid projective coordinates of secp256k1 points. That is safe in this contract, because this method is only used by linearCombination, which checks points are on the curve via ecrecover. ************************************************************************** @param px The first affine coordinate of the first summand @param py The second affine coordinate of the first summand @param qx The first affine coordinate of the second summand @param qy The second affine coordinate of the second summand (px,py) and (qx,qy) must be distinct, valid secp256k1 points. ************************************************************************** Return values are projective coordinates of [px,py,1]+[qx,qy,1] as points on secp256k1, in P²(𝔽ₙ) @return sx @return sy @return sz */ function projectiveECAdd(uint256 px, uint256 py, uint256 qx, uint256 qy) internal pure returns(uint256 sx, uint256 sy, uint256 sz) { // See "Group law for E/K : y^2 = x^3 + ax + b", in section 3.1.2, p. 80, // "Guide to Elliptic Curve Cryptography" by Hankerson, Menezes and Vanstone // We take the equations there for (sx,sy), and homogenize them to // projective coordinates. That way, no inverses are required, here, and we // only need the one inverse in affineECAdd. // We only need the "point addition" equations from Hankerson et al. Can // skip the "point doubling" equations because p1 == p2 is cryptographically // impossible, and require'd not to be the case in linearCombination. // Add extra "projective coordinate" to the two points (uint256 z1, uint256 z2) = (1, 1); // (lx, lz) = (qy-py)/(qx-px), i.e., gradient of secant line. uint256 lx = addmod(qy, FIELD_SIZE - py, FIELD_SIZE); uint256 lz = addmod(qx, FIELD_SIZE - px, FIELD_SIZE); uint256 dx; // Accumulates denominator from sx calculation // sx=((qy-py)/(qx-px))^2-px-qx (sx, dx) = projectiveMul(lx, lz, lx, lz); // ((qy-py)/(qx-px))^2 (sx, dx) = projectiveSub(sx, dx, px, z1); // ((qy-py)/(qx-px))^2-px (sx, dx) = projectiveSub(sx, dx, qx, z2); // ((qy-py)/(qx-px))^2-px-qx uint256 dy; // Accumulates denominator from sy calculation // sy=((qy-py)/(qx-px))(px-sx)-py (sy, dy) = projectiveSub(px, z1, sx, dx); // px-sx (sy, dy) = projectiveMul(sy, dy, lx, lz); // ((qy-py)/(qx-px))(px-sx) (sy, dy) = projectiveSub(sy, dy, py, z1); // ((qy-py)/(qx-px))(px-sx)-py if (dx != dy) { // Cross-multiply to put everything over a common denominator sx = mulmod(sx, dy, FIELD_SIZE); sy = mulmod(sy, dx, FIELD_SIZE); sz = mulmod(dx, dy, FIELD_SIZE); } else { // Already over a common denominator, use that for z ordinate sz = dx; } } // p1+p2, as affine points on secp256k1. // // invZ must be the inverse of the z returned by projectiveECAdd(p1, p2). // It is computed off-chain to save gas. // // p1 and p2 must be distinct, because projectiveECAdd doesn't handle // point doubling. function affineECAdd( uint256[2] memory p1, uint256[2] memory p2, uint256 invZ) internal pure returns (uint256[2] memory) { uint256 x; uint256 y; uint256 z; (x, y, z) = projectiveECAdd(p1[0], p1[1], p2[0], p2[1]); require(mulmod(z, invZ, FIELD_SIZE) == 1, "invZ must be inverse of z"); // Clear the z ordinate of the projective representation by dividing through // by it, to obtain the affine representation return [mulmod(x, invZ, FIELD_SIZE), mulmod(y, invZ, FIELD_SIZE)]; } // True iff address(c*p+s*g) == lcWitness, where g is generator. (With // cryptographically high probability.) function verifyLinearCombinationWithGenerator( uint256 c, uint256[2] memory p, uint256 s, address lcWitness) internal pure returns (bool) { // Rule out ecrecover failure modes which return address 0. require(lcWitness != address(0), "bad witness"); uint8 v = (p[1] % 2 == 0) ? 27 : 28; // parity of y-ordinate of p bytes32 pseudoHash = bytes32(GROUP_ORDER - mulmod(p[0], s, GROUP_ORDER)); // -s*p[0] bytes32 pseudoSignature = bytes32(mulmod(c, p[0], GROUP_ORDER)); // c*p[0] // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 // The point corresponding to the address returned by // ecrecover(-s*p[0],v,p[0],c*p[0]) is // (p[0]⁻¹ mod GROUP_ORDER)*(c*p[0]-(-s)*p[0]*g)=c*p+s*g. // See https://crypto.stackexchange.com/a/18106 // https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v address computed = ecrecover(pseudoHash, v, bytes32(p[0]), pseudoSignature); return computed == lcWitness; } // c*p1 + s*p2. Requires cp1Witness=c*p1 and sp2Witness=s*p2. Also // requires cp1Witness != sp2Witness (which is fine for this application, // since it is cryptographically impossible for them to be equal. In the // (cryptographically impossible) case that a prover accidentally derives // a proof with equal c*p1 and s*p2, they should retry with a different // proof nonce.) Assumes that all points are on secp256k1 // (which is checked in verifyVRFProof below.) function linearCombination( uint256 c, uint256[2] memory p1, uint256[2] memory cp1Witness, uint256 s, uint256[2] memory p2, uint256[2] memory sp2Witness, uint256 zInv) internal pure returns (uint256[2] memory) { require((cp1Witness[0] - sp2Witness[0]) % FIELD_SIZE != 0, "points in sum must be distinct"); require(ecmulVerify(p1, c, cp1Witness), "First multiplication check failed"); require(ecmulVerify(p2, s, sp2Witness), "Second multiplication check failed"); return affineECAdd(cp1Witness, sp2Witness, zInv); } // Domain-separation tag for the hash taken in scalarFromCurvePoints. // Corresponds to scalarFromCurveHashPrefix in vrf.go uint256 constant SCALAR_FROM_CURVE_POINTS_HASH_PREFIX = 2; // Pseudo-random number from inputs. Matches vrf.go/scalarFromCurvePoints, and // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 // The draft calls (in step 7, via the definition of string_to_int, in // https://datatracker.ietf.org/doc/html/rfc8017#section-4.2 ) for taking the // first hash without checking that it corresponds to a number less than the // group order, which will lead to a slight bias in the sample. // // TODO(alx): We could save a bit of gas by following the standard here and // using the compressed representation of the points, if we collated the y // parities into a single bytes32. // https://www.pivotaltracker.com/story/show/171120588 function scalarFromCurvePoints( uint256[2] memory hash, uint256[2] memory pk, uint256[2] memory gamma, address uWitness, uint256[2] memory v) internal pure returns (uint256 s) { return uint256( keccak256(abi.encodePacked(SCALAR_FROM_CURVE_POINTS_HASH_PREFIX, hash, pk, gamma, v, uWitness))); } // True if (gamma, c, s) is a correctly constructed randomness proof from pk // and seed. zInv must be the inverse of the third ordinate from // projectiveECAdd applied to cGammaWitness and sHashWitness. Corresponds to // section 5.3 of the IETF draft. // // TODO(alx): Since I'm only using pk in the ecrecover call, I could only pass // the x ordinate, and the parity of the y ordinate in the top bit of uWitness // (which I could make a uint256 without using any extra space.) Would save // about 2000 gas. https://www.pivotaltracker.com/story/show/170828567 function verifyVRFProof( uint256[2] memory pk, uint256[2] memory gamma, uint256 c, uint256 s, uint256 seed, address uWitness, uint256[2] memory cGammaWitness, uint256[2] memory sHashWitness, uint256 zInv) internal view { require(isOnCurve(pk), "public key is not on curve"); require(isOnCurve(gamma), "gamma is not on curve"); require(isOnCurve(cGammaWitness), "cGammaWitness is not on curve"); require(isOnCurve(sHashWitness), "sHashWitness is not on curve"); // Step 5. of IETF draft section 5.3 (pk corresponds to 5.3's Y, and here // we use the address of u instead of u itself. Also, here we add the // terms instead of taking the difference, and in the proof consruction in // vrf.GenerateProof, we correspondingly take the difference instead of // taking the sum as they do in step 7 of section 5.1.) require( verifyLinearCombinationWithGenerator(c, pk, s, uWitness), "addr(c*pk+s*g)≠_uWitness" ); // Step 4. of IETF draft section 5.3 (pk corresponds to Y, seed to alpha_string) uint256[2] memory hash = hashToCurve(pk, seed); // Step 6. of IETF draft section 5.3, but see note for step 5 about +/- terms uint256[2] memory v = linearCombination( c, gamma, cGammaWitness, s, hash, sHashWitness, zInv); // Steps 7. and 8. of IETF draft section 5.3 uint256 derivedC = scalarFromCurvePoints(hash, pk, gamma, uWitness, v); require(c == derivedC, "invalid proof"); } // Domain-separation tag for the hash used as the final VRF output. // Corresponds to vrfRandomOutputHashPrefix in vrf.go uint256 constant VRF_RANDOM_OUTPUT_HASH_PREFIX = 3; // Length of proof marshaled to bytes array. Shows layout of proof uint public constant PROOF_LENGTH = 64 + // PublicKey (uncompressed format.) 64 + // Gamma 32 + // C 32 + // S 32 + // Seed 0 + // Dummy entry: The following elements are included for gas efficiency: 32 + // uWitness (gets padded to 256 bits, even though it's only 160) 64 + // cGammaWitness 64 + // sHashWitness 32; // zInv (Leave Output out, because that can be efficiently calculated) /* *************************************************************************** * @notice Returns proof's output, if proof is valid. Otherwise reverts * @param proof A binary-encoded proof, as output by vrf.Proof.MarshalForSolidityVerifier * * Throws if proof is invalid, otherwise: * @return output i.e., the random output implied by the proof * *************************************************************************** * @dev See the calculation of PROOF_LENGTH for the binary layout of proof. */ function randomValueFromVRFProof(bytes memory proof) internal view returns (uint256 output) { require(proof.length == PROOF_LENGTH, "wrong proof length"); uint256[2] memory pk; // parse proof contents into these variables uint256[2] memory gamma; // c, s and seed combined (prevents "stack too deep" compilation error) uint256[3] memory cSSeed; address uWitness; uint256[2] memory cGammaWitness; uint256[2] memory sHashWitness; uint256 zInv; (pk, gamma, cSSeed, uWitness, cGammaWitness, sHashWitness, zInv) = abi.decode( proof, (uint256[2], uint256[2], uint256[3], address, uint256[2], uint256[2], uint256)); verifyVRFProof( pk, gamma, cSSeed[0], // c cSSeed[1], // s cSSeed[2], // seed uWitness, cGammaWitness, sHashWitness, zInv ); output = uint256(keccak256(abi.encode(VRF_RANDOM_OUTPUT_HASH_PREFIX, gamma))); } } // File: contracts/VRFRequestIDBase.sol pragma solidity ^0.6.0; contract VRFRequestIDBase { /** * @notice returns the seed which is actually input to the VRF coordinator * * @dev To prevent repetition of VRF output due to repetition of the * @dev user-supplied seed, that seed is combined in a hash with the * @dev user-specific nonce, and the address of the consuming contract. The * @dev risk of repetition is mostly mitigated by inclusion of a blockhash in * @dev the final seed, but the nonce does protect against repetition in * @dev requests which are included in a single block. * * @param _userSeed VRF seed input provided by user * @param _requester Address of the requesting contract * @param _nonce User-specific nonce at the time of the request */ function makeVRFInputSeed(bytes32 _keyHash, uint256 _userSeed, address _requester, uint256 _nonce) internal pure returns (uint256) { return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce))); } /** * @notice Returns the id for this request * @param _keyHash The serviceAgreement ID to be used for this request * @param _vRFInputSeed The seed to be passed directly to the VRF * @return The id for this request * * @dev Note that _vRFInputSeed is not the seed passed by the consuming * @dev contract, but the one generated by makeVRFInputSeed */ function makeRequestId( bytes32 _keyHash, uint256 _vRFInputSeed) internal pure returns (bytes32) { return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed)); } } // File: contracts/VRFConsumerBase.sol pragma solidity ^0.6.0; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerInterface, and can * @dev initialize VRFConsumerInterface's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constuctor(<other arguments>, address _vrfCoordinator, address _link) * @dev VRFConsumerBase(_vrfCoordinator, _link) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash), and have told you the minimum LINK * @dev price for VRF service. Make sure your contract has sufficient LINK, and * @dev call requestRandomness(keyHash, fee, seed), where seed is the input you * @dev want to generate randomness from. * * @dev Once the VRFCoordinator has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomness method. * * @dev The randomness argument to fulfillRandomness is the actual random value * @dev generated from your seed. * * @dev The requestId argument is generated from the keyHash and the seed by * @dev makeRequestId(keyHash, seed). If your contract could have concurrent * @dev requests open, you can use the requestId to track which seed is * @dev associated with which randomness. See VRFRequestIDBase.sol for more * @dev details. * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. (Which is critical to making unpredictable randomness! See the * @dev next section.) * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev Since the ultimate input to the VRF is mixed with the block hash of the * @dev block in which the request is made, user-provided seeds have no impact * @dev on its economic security properties. They are only included for API * @dev compatability with previous versions of this contract. * * @dev Since the block hash of the block which contains the requestRandomness() * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls fulfillRandomness(). */ abstract contract VRFConsumerBase is VRFRequestIDBase { using SafeMath for uint256; /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. * * @dev The VRFCoordinator expects a calling contract to have a method with * @dev this signature, and will trigger it once it has verified the proof * @dev associated with the randomness (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomness the VRF output */ function fulfillRandomness(bytes32 requestId, uint256 randomness) internal virtual; /** * @notice requestRandomness initiates a request for VRF output given _seed * * @dev See "SECURITY CONSIDERATIONS" above for more information on _seed. * * @dev The fulfillRandomness method receives the output, once it's provided * @dev by the Oracle, and verified by the vrfCoordinator. * * @dev The _keyHash must already be registered with the VRFCoordinator, and * @dev the _fee must exceed the fee specified during registration of the * @dev _keyHash. * * @param _keyHash ID of public key against which randomness is generated * @param _fee The amount of LINK to send with the request * @param _seed seed mixed into the input of the VRF * * @return requestId unique ID for this request * * @dev The returned requestId can be used to distinguish responses to * * @dev concurrent requests. It is passed as the first argument to * @dev fulfillRandomness. */ function requestRandomness(bytes32 _keyHash, uint256 _fee, uint256 _seed) public returns (bytes32 requestId) { LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, _seed)); // This is the seed passed to VRFCoordinator. The oracle will mix this with // the hash of the block containing this request to obtain the seed/input // which is finally passed to the VRF cryptographic machinery. uint256 vRFSeed = makeVRFInputSeed(_keyHash, _seed, address(this), nonces[_keyHash]); // nonces[_keyHash] must stay in sync with // VRFCoordinator.nonces[_keyHash][this], which was incremented by the above // successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest). // This provides protection against the user repeating their input // seed, which would result in a predictable/duplicate output. nonces[_keyHash] = nonces[_keyHash].add(1); return makeRequestId(_keyHash, vRFSeed); } LinkTokenInterface immutable internal LINK; address immutable private vrfCoordinator; // Nonces for each VRF key from which randomness has been requested. // // Must stay in sync with VRFCoordinator[_keyHash][this] mapping(bytes32 /* keyHash */ => uint256 /* nonce */) public nonces; constructor(address _vrfCoordinator, address _link) public { vrfCoordinator = _vrfCoordinator; LINK = LinkTokenInterface(_link); } // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external { require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill"); fulfillRandomness(requestId, randomness); } } // File: contracts/VRFCoordinator.sol pragma solidity 0.6.6; /** * @title VRFCoordinator coordinates on-chain verifiable-randomness requests * @title with off-chain responses */ contract VRFCoordinator is VRF, VRFRequestIDBase { using SafeMath for uint256; LinkTokenInterface internal LINK; BlockHashStoreInterface internal blockHashStore; constructor(address _link, address _blockHashStore) public { LINK = LinkTokenInterface(_link); blockHashStore = BlockHashStoreInterface(_blockHashStore); } struct Callback { // Tracks an ongoing request address callbackContract; // Requesting contract, which will receive response // Amount of LINK paid at request time. Total LINK = 1e9 * 1e18 < 2^96, so // this representation is adequate, and saves a word of storage when this // field follows the 160-bit callbackContract address. uint96 randomnessFee; // Commitment to seed passed to oracle by this contract, and the number of // the block in which the request appeared. This is the keccak256 of the // concatenation of those values. Storing this commitment saves a word of // storage. bytes32 seedAndBlockNum; } struct ServiceAgreement { // Tracks oracle commitments to VRF service address vRFOracle; // Oracle committing to respond with VRF service uint96 fee; // Minimum payment for oracle response. Total LINK=1e9*1e18<2^96 bytes32 jobID; // ID of corresponding chainlink job in oracle's DB } mapping(bytes32 /* (provingKey, seed) */ => Callback) public callbacks; mapping(bytes32 /* provingKey */ => ServiceAgreement) public serviceAgreements; mapping(address /* oracle */ => uint256 /* LINK balance */) public withdrawableTokens; mapping(bytes32 /* provingKey */ => mapping(address /* consumer */ => uint256)) private nonces; // The oracle only needs the jobID to look up the VRF, but specifying public // key as well prevents a malicious oracle from inducing VRF outputs from // another oracle by reusing the jobID. event RandomnessRequest( bytes32 keyHash, uint256 seed, bytes32 indexed jobID, address sender, uint256 fee, bytes32 requestID); event NewServiceAgreement(bytes32 keyHash, uint256 fee); event RandomnessRequestFulfilled(bytes32 requestId, uint256 output); /** * @notice Commits calling address to serve randomness * @param _fee minimum LINK payment required to serve randomness * @param _oracle the address of the Chainlink node with the proving key and job * @param _publicProvingKey public key used to prove randomness * @param _jobID ID of the corresponding chainlink job in the oracle's db */ function registerProvingKey( uint256 _fee, address _oracle, uint256[2] calldata _publicProvingKey, bytes32 _jobID ) external { bytes32 keyHash = hashOfKey(_publicProvingKey); address oldVRFOracle = serviceAgreements[keyHash].vRFOracle; require(oldVRFOracle == address(0), "please register a new key"); require(_oracle != address(0), "_oracle must not be 0x0"); serviceAgreements[keyHash].vRFOracle = _oracle; serviceAgreements[keyHash].jobID = _jobID; // Yes, this revert message doesn't fit in a word require(_fee <= 1e9 ether, "you can't charge more than all the LINK in the world, greedy"); serviceAgreements[keyHash].fee = uint96(_fee); emit NewServiceAgreement(keyHash, _fee); } /** * @notice Called by LINK.transferAndCall, on successful LINK transfer * * @dev To invoke this, use the requestRandomness method in VRFConsumerBase. * * @dev The VRFCoordinator will call back to the calling contract when the * @dev oracle responds, on the method fulfillRandomness. See * @dev VRFConsumerBase.fulfilRandomness for its signature. Your consuming * @dev contract should inherit from VRFConsumerBase, and implement * @dev fulfilRandomness. * * @param _sender address: who sent the LINK (must be a contract) * @param _fee amount of LINK sent * @param _data abi-encoded call to randomnessRequest */ function onTokenTransfer(address _sender, uint256 _fee, bytes memory _data) public onlyLINK { (bytes32 keyHash, uint256 seed) = abi.decode(_data, (bytes32, uint256)); randomnessRequest(keyHash, seed, _fee, _sender); } /** * @notice creates the chainlink request for randomness * * @param _keyHash ID of the VRF public key against which to generate output * @param _consumerSeed Input to the VRF, from which randomness is generated * @param _feePaid Amount of LINK sent with request. Must exceed fee for key * @param _sender Requesting contract; to be called back with VRF output * * @dev _consumerSeed is mixed with key hash, sender address and nonce to * @dev obtain preSeed, which is passed to VRF oracle, which mixes it with the * @dev hash of the block containing this request, to compute the final seed. * * @dev The requestId used to store the request data is constructed from the * @dev preSeed and keyHash. */ function randomnessRequest( bytes32 _keyHash, uint256 _consumerSeed, uint256 _feePaid, address _sender ) internal sufficientLINK(_feePaid, _keyHash) { uint256 nonce = nonces[_keyHash][_sender]; uint256 preSeed = makeVRFInputSeed(_keyHash, _consumerSeed, _sender, nonce); bytes32 requestId = makeRequestId(_keyHash, preSeed); // Cryptographically guaranteed by preSeed including an increasing nonce assert(callbacks[requestId].callbackContract == address(0)); callbacks[requestId].callbackContract = _sender; assert(_feePaid < 1e27); // Total LINK fits in uint96 callbacks[requestId].randomnessFee = uint96(_feePaid); callbacks[requestId].seedAndBlockNum = keccak256(abi.encodePacked( preSeed, block.number)); emit RandomnessRequest(_keyHash, preSeed, serviceAgreements[_keyHash].jobID, _sender, _feePaid, requestId); nonces[_keyHash][_sender] = nonces[_keyHash][_sender].add(1); } // Offsets into fulfillRandomnessRequest's _proof of various values // // Public key. Skips byte array's length prefix. uint256 public constant PUBLIC_KEY_OFFSET = 0x20; // Seed is 7th word in proof, plus word for length, (6+1)*0x20=0xe0 uint256 public constant PRESEED_OFFSET = 0xe0; /** * @notice Called by the chainlink node to fulfill requests * * @param _proof the proof of randomness. Actual random output built from this * * @dev The structure of _proof corresponds to vrf.MarshaledOnChainResponse, * @dev in the node source code. I.e., it is a vrf.MarshaledProof with the * @dev seed replaced by the preSeed, followed by the hash of the requesting * @dev block. */ function fulfillRandomnessRequest(bytes memory _proof) public { (bytes32 currentKeyHash, Callback memory callback, bytes32 requestId, uint256 randomness) = getRandomnessFromProof(_proof); // Pay oracle address oadd = serviceAgreements[currentKeyHash].vRFOracle; withdrawableTokens[oadd] = withdrawableTokens[oadd].add( callback.randomnessFee); // Forget request. Must precede callback (prevents reentrancy) delete callbacks[requestId]; callBackWithRandomness(requestId, randomness, callback.callbackContract); emit RandomnessRequestFulfilled(requestId, randomness); } function callBackWithRandomness(bytes32 requestId, uint256 randomness, address consumerContract) internal { // Dummy variable; allows access to method selector in next line. See // https://github.com/ethereum/solidity/issues/3506#issuecomment-553727797 VRFConsumerBase v; bytes memory resp = abi.encodeWithSelector( v.rawFulfillRandomness.selector, requestId, randomness); // The bound b here comes from https://eips.ethereum.org/EIPS/eip-150. The // actual gas available to the consuming contract will be b-floor(b/64). // This is chosen to leave the consuming contract ~200k gas, after the cost // of the call itself. uint256 b = 206000; require(gasleft() >= b, "not enough gas for consumer"); // A low-level call is necessary, here, because we don't want the consuming // contract to be able to revert this execution, and thus deny the oracle // payment for a valid randomness response. This also necessitates the above // check on the gasleft, as otherwise there would be no indication if the // callback method ran out of gas. // // solhint-disable-next-line avoid-low-level-calls (bool success,) = consumerContract.call(resp); // Avoid unused-local-variable warning. (success is only present to prevent // a warning that the return value of consumerContract.call is unused.) (success); } function getRandomnessFromProof(bytes memory _proof) internal view returns (bytes32 currentKeyHash, Callback memory callback, bytes32 requestId, uint256 randomness) { // blockNum follows proof, which follows length word (only direct-number // constants are allowed in assembly, so have to compute this in code) uint256 BLOCKNUM_OFFSET = 0x20 + PROOF_LENGTH; // _proof.length skips the initial length word, so not including the // blocknum in this length check balances out. require(_proof.length == BLOCKNUM_OFFSET, "wrong proof length"); uint256[2] memory publicKey; uint256 preSeed; uint256 blockNum; assembly { // solhint-disable-line no-inline-assembly publicKey := add(_proof, PUBLIC_KEY_OFFSET) preSeed := mload(add(_proof, PRESEED_OFFSET)) blockNum := mload(add(_proof, BLOCKNUM_OFFSET)) } currentKeyHash = hashOfKey(publicKey); requestId = makeRequestId(currentKeyHash, preSeed); callback = callbacks[requestId]; require(callback.callbackContract != address(0), "no corresponding request"); require(callback.seedAndBlockNum == keccak256(abi.encodePacked(preSeed, blockNum)), "wrong preSeed or block num"); bytes32 blockHash = blockhash(blockNum); if (blockHash == bytes32(0)) { blockHash = blockHashStore.getBlockhash(blockNum); require(blockHash != bytes32(0), "please prove blockhash"); } // The seed actually used by the VRF machinery, mixing in the blockhash uint256 actualSeed = uint256(keccak256(abi.encodePacked(preSeed, blockHash))); // solhint-disable-next-line no-inline-assembly assembly { // Construct the actual proof from the remains of _proof mstore(add(_proof, PRESEED_OFFSET), actualSeed) mstore(_proof, PROOF_LENGTH) } randomness = VRF.randomValueFromVRFProof(_proof); // Reverts on failure } /** * @dev Allows the oracle operator to withdraw their LINK * @param _recipient is the address the funds will be sent to * @param _amount is the amount of LINK transferred from the Coordinator contract */ function withdraw(address _recipient, uint256 _amount) external hasAvailableFunds(_amount) { withdrawableTokens[msg.sender] = withdrawableTokens[msg.sender].sub(_amount); assert(LINK.transfer(_recipient, _amount)); } /** * @notice Returns the serviceAgreements key associated with this public key * @param _publicKey the key to return the address for */ function hashOfKey(uint256[2] memory _publicKey) public pure returns (bytes32) { return keccak256(abi.encodePacked(_publicKey)); } /** * @dev Reverts if amount is not at least what was agreed upon in the service agreement * @param _feePaid The payment for the request * @param _keyHash The key which the request is for */ modifier sufficientLINK(uint256 _feePaid, bytes32 _keyHash) { require(_feePaid >= serviceAgreements[_keyHash].fee, "Below agreed payment"); _; } /** * @dev Reverts if not sent from the LINK token */ modifier onlyLINK() { require(msg.sender == address(LINK), "Must use LINK token"); _; } /** * @dev Reverts if amount requested is greater than withdrawable balance * @param _amount The given amount to compare to `withdrawableTokens` */ modifier hasAvailableFunds(uint256 _amount) { require(withdrawableTokens[msg.sender] >= _amount, "can't withdraw more than balance"); _; } }
[{"inputs":[{"internalType":"address","name":"_link","type":"address"},{"internalType":"address","name":"_blockHashStore","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"keyHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"NewServiceAgreement","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"keyHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"seed","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"jobID","type":"bytes32"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"requestID","type":"bytes32"}],"name":"RandomnessRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"output","type":"uint256"}],"name":"RandomnessRequestFulfilled","type":"event"},{"inputs":[],"name":"PRESEED_OFFSET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROOF_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_KEY_OFFSET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"callbacks","outputs":[{"internalType":"address","name":"callbackContract","type":"address"},{"internalType":"uint96","name":"randomnessFee","type":"uint96"},{"internalType":"bytes32","name":"seedAndBlockNum","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_proof","type":"bytes"}],"name":"fulfillRandomnessRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"_publicKey","type":"uint256[2]"}],"name":"hashOfKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"uint256[2]","name":"_publicProvingKey","type":"uint256[2]"},{"internalType":"bytes32","name":"_jobID","type":"bytes32"}],"name":"registerProvingKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"serviceAgreements","outputs":[{"internalType":"address","name":"vRFOracle","type":"address"},{"internalType":"uint96","name":"fee","type":"uint96"},{"internalType":"bytes32","name":"jobID","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"withdrawableTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50604051611e3e380380611e3e8339818101604052604081101561003357600080fd5b508051602090910151600080546001600160a01b039384166001600160a01b03199182161790915560018054939092169216919091179055611dc48061007a6000396000f3fe608060405234801561001057600080fd5b50600436106100a85760003560e01c8063a4c0ed3611610071578063a4c0ed36146101ff578063b415f4f5146102ba578063caf70c4a146102c2578063d83402091461030d578063e911439c14610344578063f3fef3a31461034c576100a8565b80626f6ad0146100ad57806321f36509146100e55780635e1c10591461013257806375d35070146101da5780638aa7927b146101f7575b600080fd5b6100d3600480360360208110156100c357600080fd5b50356001600160a01b0316610378565b60408051918252519081900360200190f35b610102600480360360208110156100fb57600080fd5b503561038a565b604080516001600160a01b0390941684526001600160601b03909216602084015282820152519081900360600190f35b6101d86004803603602081101561014857600080fd5b81019060208101813564010000000081111561016357600080fd5b82018360208201111561017557600080fd5b8035906020019184600183028401116401000000008311171561019757600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506103bf945050505050565b005b610102600480360360208110156101f057600080fd5b50356104a8565b6100d36104dd565b6101d86004803603606081101561021557600080fd5b6001600160a01b038235169160208101359181019060608101604082013564010000000081111561024557600080fd5b82018360208201111561025757600080fd5b8035906020019184600183028401116401000000008311171561027957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506104e2945050505050565b6100d3610570565b6100d3600480360360408110156102d857600080fd5b604080518082018252918301929181830191839060029083908390808284376000920191909152509194506105759350505050565b6101d8600480360360a081101561032357600080fd5b508035906001600160a01b03602082013516906040810190608001356105cb565b6100d36107ab565b6101d86004803603604081101561036257600080fd5b506001600160a01b0381351690602001356107b1565b60046020526000908152604090205481565b600260205260009081526040902080546001909101546001600160a01b03821691600160a01b90046001600160601b03169083565b60006103c9611c77565b6000806103d5856108d3565b600084815260036020908152604080832054828701516001600160a01b03909116808552600490935292205495995093975091955093509091610426916001600160601b031663ffffffff610b9716565b6001600160a01b038216600090815260046020908152604080832093909355858252600290529081208181556001015583516104659084908490610bfa565b604080518481526020810184905281517fa2e7a402243ebda4a69ceeb3dfb682943b7a9b3ac66d6eefa8db65894009611c929181900390910190a1505050505050565b600360205260009081526040902080546001909101546001600160a01b03821691600160a01b90046001600160601b03169083565b602081565b6000546001600160a01b03163314610537576040805162461bcd60e51b815260206004820152601360248201527226bab9ba103ab9b2902624a725903a37b5b2b760691b604482015290519081900360640190fd5b60008082806020019051604081101561054f57600080fd5b508051602090910151909250905061056982828688610d44565b5050505050565b60e081565b6000816040516020018082600260200280838360005b838110156105a357818101518382015260200161058b565b505050509050019150506040516020818303038152906040528051906020012090505b919050565b6040805180820182526000916105fa919085906002908390839080828437600092019190915250610575915050565b6000818152600360205260409020549091506001600160a01b03168015610668576040805162461bcd60e51b815260206004820152601960248201527f706c656173652072656769737465722061206e6577206b657900000000000000604482015290519081900360640190fd5b6001600160a01b0385166106c3576040805162461bcd60e51b815260206004820152601760248201527f5f6f7261636c65206d757374206e6f7420626520307830000000000000000000604482015290519081900360640190fd5b600082815260036020526040902080546001600160a01b0319166001600160a01b0387161781556001018390556b033b2e3c9fd0803ce800000086111561073b5760405162461bcd60e51b815260040180806020018281038252603c815260200180611d10603c913960400191505060405180910390fd5b60008281526003602090815260409182902080546001600160a01b0316600160a01b6001600160601b038b1602179055815184815290810188905281517fae189157e0628c1e62315e9179156e1ea10e90e9c15060002f7021e907dc2cfe929181900390910190a1505050505050565b6101a081565b336000908152600460205260409020548190811115610817576040805162461bcd60e51b815260206004820181905260248201527f63616e2774207769746864726177206d6f7265207468616e2062616c616e6365604482015290519081900360640190fd5b33600090815260046020526040902054610837908363ffffffff610f7016565b336000908152600460208181526040808420949094558254845163a9059cbb60e01b81526001600160a01b038981169482019490945260248101889052945192169363a9059cbb93604480830194928390030190829087803b15801561089c57600080fd5b505af11580156108b0573d6000803e3d6000fd5b505050506040513d60208110156108c657600080fd5b50516108ce57fe5b505050565b60006108dd611c77565b825160009081906101c0908114610930576040805162461bcd60e51b81526020600482015260126024820152710eee4dedcce40e0e4dedecc40d8cadccee8d60731b604482015290519081900360640190fd5b610938611c97565b5060e08601518187015160208801919061095183610575565b975061095d8883610fcd565b600081815260026020908152604091829020825160608101845281546001600160a01b038116808352600160a01b9091046001600160601b03169382019390935260019091015492810192909252909850909650610a02576040805162461bcd60e51b815260206004820152601860248201527f6e6f20636f72726573706f6e64696e6720726571756573740000000000000000604482015290519081900360640190fd5b6040805160208082018590528183018490528251808303840181526060909201835281519101209088015114610a7f576040805162461bcd60e51b815260206004820152601a60248201527f77726f6e672070726553656564206f7220626c6f636b206e756d000000000000604482015290519081900360640190fd5b804080610b4b5760015460408051631d2827a760e31b81526004810185905290516001600160a01b039092169163e9413d3891602480820192602092909190829003018186803b158015610ad257600080fd5b505afa158015610ae6573d6000803e3d6000fd5b505050506040513d6020811015610afc57600080fd5b5051905080610b4b576040805162461bcd60e51b81526020600482015260166024820152750e0d8cac2e6ca40e0e4deecca40c4d8dec6d6d0c2e6d60531b604482015290519081900360640190fd5b6040805160208082018690528183018490528251808303840181526060909201909252805191012060e08b018190526101a08b52610b888b610ff9565b96505050505050509193509193565b600082820183811015610bf1576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b604080516024810185905260448082018590528251808303909101815260649091019091526020810180516001600160e01b03166394985ddd60e01b179052600090620324b0805a1015610c95576040805162461bcd60e51b815260206004820152601b60248201527f6e6f7420656e6f7567682067617320666f7220636f6e73756d65720000000000604482015290519081900360640190fd5b6000846001600160a01b0316836040518082805190602001908083835b60208310610cd15780518252601f199092019160209182019101610cb2565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610d33576040519150601f19603f3d011682016040523d82523d6000602084013e610d38565b606091505b50505050505050505050565b60008481526003602052604090205482908590600160a01b90046001600160601b0316821015610db2576040805162461bcd60e51b815260206004820152601460248201527310995b1bddc81859dc995959081c185e5b595b9d60621b604482015290519081900360640190fd5b60008681526005602090815260408083206001600160a01b038716845290915281205490610de288888785611142565b90506000610df08983610fcd565b6000818152600260205260409020549091506001600160a01b031615610e1257fe5b600081815260026020526040902080546001600160a01b0319166001600160a01b0388161790556b033b2e3c9fd0803ce80000008710610e4e57fe5b600081815260026020908152604080832080546001600160601b038c16600160a01b026001600160a01b0391821617825582518085018890524381850152835180820385018152606082018086528151918701919091206001948501558f875260039095529483902090910154928d905260808401869052891660a084015260c083018a905260e083018490525190917f56bd374744a66d531874338def36c906e3a6cf31176eb1e9afd9f1de69725d5191908190036101000190a260008981526005602090815260408083206001600160a01b038a168452909152902054610f3e90600163ffffffff610b9716565b6000998a52600560209081526040808c206001600160a01b039099168c52979052959098209490945550505050505050565b600082821115610fc7576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60006101a0825114611047576040805162461bcd60e51b81526020600482015260126024820152710eee4dedcce40e0e4dedecc40d8cadccee8d60731b604482015290519081900360640190fd5b61104f611c97565b611057611c97565b61105f611cb5565b6000611069611c97565b611071611c97565b6000888060200190516101a081101561108957600080fd5b5060e08101516101808201519198506040890197506080890196509450610100880193506101408801925090506110dc878787600060200201518860016020020151896002602002015189898989611189565b6003866040516020018083815260200182600260200280838360005b838110156111105781810151838201526020016110f8565b50505050905001925050506040516020818303038152906040528051906020012060001c975050505050505050919050565b60408051602080820196909652808201949094526001600160a01b039290921660608401526080808401919091528151808403909101815260a09092019052805191012090565b611192896113d6565b6111e3576040805162461bcd60e51b815260206004820152601a60248201527f7075626c6963206b6579206973206e6f74206f6e206375727665000000000000604482015290519081900360640190fd5b6111ec886113d6565b611235576040805162461bcd60e51b815260206004820152601560248201527467616d6d61206973206e6f74206f6e20637572766560581b604482015290519081900360640190fd5b61123e836113d6565b61128f576040805162461bcd60e51b815260206004820152601d60248201527f6347616d6d615769746e657373206973206e6f74206f6e206375727665000000604482015290519081900360640190fd5b611298826113d6565b6112e9576040805162461bcd60e51b815260206004820152601c60248201527f73486173685769746e657373206973206e6f74206f6e20637572766500000000604482015290519081900360640190fd5b6112f5878a8887611400565b611346576040805162461bcd60e51b815260206004820152601a60248201527f6164647228632a706b2b732a6729e289a05f755769746e657373000000000000604482015290519081900360640190fd5b61134e611c97565b6113588a8761152e565b9050611362611c97565b611371898b878b8689896115d1565b90506000611382838d8d8a866116dc565b9050808a146113c8576040805162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b604482015290519081900360640190fd5b505050505050505050505050565b60208101516000906401000003d0199080096113f98360005b60200201516117e5565b1492915050565b60006001600160a01b03821661144b576040805162461bcd60e51b815260206004820152600b60248201526a626164207769746e65737360a81b604482015290519081900360640190fd5b60208401516000906001161561146257601c611465565b601b5b9050600070014551231950b75fc4402da1732fc9bebe1985876000602002015109865170014551231950b75fc4402da1732fc9bebe1991820392506000919089098751604080516000808252602082810180855288905260ff8916838501526060830194909452608082018590529151939450909260019260a0808401939192601f1981019281900390910190855afa158015611506573d6000803e3d6000fd5b5050604051601f1901516001600160a01b039081169088161495505050505050949350505050565b611536611c97565b611594600184846040516020018084815260200183600260200280838360005b8381101561156e578181015183820152602001611556565b505050509050018281526020019350505050604051602081830303815290604052611809565b90505b6115a0816113d6565b610bf45780516040805160208181019390935281518082039093018352810190526115ca90611809565b9050611597565b6115d9611c97565b825186516401000003d01991900306611639576040805162461bcd60e51b815260206004820152601e60248201527f706f696e747320696e2073756d206d7573742062652064697374696e63740000604482015290519081900360640190fd5b611644878988611857565b61167f5760405162461bcd60e51b8152600401808060200182810382526021815260200180611d4c6021913960400191505060405180910390fd5b61168a848685611857565b6116c55760405162461bcd60e51b8152600401808060200182810382526022815260200180611d6d6022913960400191505060405180910390fd5b6116d0868484611977565b98975050505050505050565b6000600286868685876040516020018087815260200186600260200280838360005b838110156117165781810151838201526020016116fe565b5050505090500185600260200280838360005b83811015611741578181015183820152602001611729565b5050505090500184600260200280838360005b8381101561176c578181015183820152602001611754565b5050505090500183600260200280838360005b8381101561179757818101518382015260200161177f565b50505050905001826001600160a01b03166001600160a01b031660601b815260140196505050505050506040516020818303038152906040528051906020012060001c905095945050505050565b6000806401000003d01980848509840990506401000003d019600782089392505050565b611811611c97565b61181a82611a3d565b815261182f61182a8260006113ef565b611a78565b6020820181905260029006600114156105c6576020810180516401000003d019039052919050565b60008261186357600080fd5b835160208501516000906001161561187c57601c61187f565b601b5b9050600070014551231950b75fc4402da1732fc9bebe19838709604080516000808252602080830180855282905260ff871683850152606083018890526080830185905292519394509260019260a0808401939192601f1981019281900390910190855afa1580156118f5573d6000803e3d6000fd5b5050506020604051035190506000866040516020018082600260200280838360005b8381101561192f578181015183820152602001611917565b505050509050019150506040516020818303038152906040528051906020012060001c9050806001600160a01b0316826001600160a01b031614955050505050509392505050565b61197f611c97565b8351602080860151855191860151600093849384936119a093909190611a8e565b919450925090506401000003d019858209600114611a05576040805162461bcd60e51b815260206004820152601960248201527f696e765a206d75737420626520696e7665727365206f66207a00000000000000604482015290519081900360640190fd5b60405180604001604052806401000003d01980611a1e57fe5b87860981526020016401000003d0198785099052979650505050505050565b805160208201205b6401000003d01981106105c657604080516020808201939093528151808203840181529082019091528051910120611a45565b6000610bf48263400000f4600160fe1b03611b6e565b60008080600180826401000003d019896401000003d019038808905060006401000003d0198b6401000003d019038a0890506000611ace83838585611c0a565b9098509050611adf88828e88611c2e565b9098509050611af088828c87611c2e565b90985090506000611b038d878b85611c2e565b9098509050611b1488828686611c0a565b9098509050611b2588828e89611c2e565b9098509050818114611b5a576401000003d019818a0998506401000003d01982890997506401000003d0198183099650611b5e565b8196505b5050505050509450945094915050565b600080611b79611cd3565b6020808252818101819052604082015260608101859052608081018490526401000003d01960a0820152611bab611cf1565b60208160c0846005600019fa925082611c00576040805162461bcd60e51b81526020600482015260126024820152716269674d6f64457870206661696c7572652160701b604482015290519081900360640190fd5b5195945050505050565b6000806401000003d0198487096401000003d0198487099097909650945050505050565b600080806401000003d019878509905060006401000003d01987876401000003d019030990506401000003d0198183086401000003d01986890990999098509650505050505050565b604080516060810182526000808252602082018190529181019190915290565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b6040518060200160405280600190602082028036833750919291505056fe796f752063616e277420636861726765206d6f7265207468616e20616c6c20746865204c494e4b20696e2074686520776f726c642c206772656564794669727374206d756c7469706c69636174696f6e20636865636b206661696c65645365636f6e64206d756c7469706c69636174696f6e20636865636b206661696c6564a2646970667358221220161162074d9bf07615abb7876be2741cd4650817f75243f60750bea841412fa664736f6c63430006060033000000000000000000000000326c977e6efc84e512bb9c30f76e30c160ed06fb000000000000000000000000328e89be1ca9e6b33fad9502d7341a6438c58ab2
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000326c977e6efc84e512bb9c30f76e30c160ed06fb000000000000000000000000328e89be1ca9e6b33fad9502d7341a6438c58ab2
-----Decoded View---------------
Arg [0] : _link (address): 0x326c977e6efc84e512bb9c30f76e30c160ed06fb
Arg [1] : _blockHashStore (address): 0x328e89be1ca9e6b33fad9502d7341a6438c58ab2
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000326c977e6efc84e512bb9c30f76e30c160ed06fb
Arg [1] : 000000000000000000000000328e89be1ca9e6b33fad9502d7341a6438c58ab2
Deployed ByteCode Sourcemap
41366:12338:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;41366:12338:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;42860:90:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;42860:90:0;-1:-1:-1;;;;;42860:90:0;;:::i;:::-;;;;;;;;;;;;;;;;42697:70;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;42697:70:0;;:::i;:::-;;;;-1:-1:-1;;;;;42697:70:0;;;;;-1:-1:-1;;;;;42697:70:0;;;;;;;;;;;;;;;;;;;;48098:629;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;48098:629:0;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;48098:629:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;48098:629:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;48098:629:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;48098:629:0;;-1:-1:-1;48098:629:0;;-1:-1:-1;;;;;48098:629:0:i;:::-;;42772:83;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;42772:83:0;;:::i;47495:48::-;;;:::i;45364:243::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;45364:243:0;;;;;;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;45364:243:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;45364:243:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;45364:243:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;45364:243:0;;-1:-1:-1;45364:243:0;;-1:-1:-1;;;;;45364:243:0:i;47619:45::-;;;:::i;52699:138::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;52699:138:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;52699:138:0;;-1:-1:-1;52699:138:0;;-1:-1:-1;;;;52699:138:0:i;43928:759::-;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;43928:759:0;;;-1:-1:-1;;;;;43928:759:0;;;;;;;;;;;;;;:::i;30029:360::-;;;:::i;52299:242::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;52299:242:0;;;;;;;;:::i;42860:90::-;;;;;;;;;;;;;:::o;42697:70::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;42697:70:0;;;-1:-1:-1;;;42697:70:0;;-1:-1:-1;;;;;42697:70:0;;;:::o;48098:629::-;48168:22;48192:24;;:::i;:::-;48218:17;48243:18;48265:30;48288:6;48265:22;:30::i;:::-;48323:12;48338:33;;;:17;:33;;;;;;;;:43;48452:22;;;;-1:-1:-1;;;;;48338:43:0;;;48415:24;;;:18;:24;;;;;;48167:128;;-1:-1:-1;48167:128:0;;-1:-1:-1;48167:128:0;;-1:-1:-1;48167:128:0;-1:-1:-1;48338:43:0;;48415:60;;-1:-1:-1;;;;;48415:60:0;;:28;:60;:::i;:::-;-1:-1:-1;;;;;48388:24:0;;;;;;:18;:24;;;;;;;;:87;;;;48559:20;;;:9;:20;;;;;48552:27;;;;;;48632:25;;48586:72;;48569:9;;48620:10;;48586:22;:72::i;:::-;48672:49;;;;;;;;;;;;;;;;;;;;;;;;;48098:629;;;;;;:::o;42772:83::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;42772:83:0;;;-1:-1:-1;;;42772:83:0;;-1:-1:-1;;;;;42772:83:0;;;:::o;47495:48::-;47539:4;47495:48;:::o;45364:243::-;53336:4;;-1:-1:-1;;;;;53336:4:0;53314:10;:27;53306:59;;;;;-1:-1:-1;;;53306:59:0;;;;;;;;;;;;-1:-1:-1;;;53306:59:0;;;;;;;;;;;;;;;45477:15:::1;45494:12:::0;45521:5:::1;45510:37;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;45510:37:0;;::::1;::::0;;::::1;::::0;;;-1:-1:-1;45510:37:0;-1:-1:-1;45554:47:0::1;45510:37:::0;;45587:4;45593:7;45554:17:::1;:47::i;:::-;53372:1;;45364:243:::0;;;:::o;47619:45::-;47660:4;47619:45;:::o;52699:138::-;52769:7;52819:10;52802:28;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;52802:28:0;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;52802:28:0;;;52792:39;;;;;;52785:46;;52699:138;;;;:::o;43928:759::-;44094:28;;;;;;;;44076:15;;44094:28;;;44104:17;;44094:28;;;;44104:17;;44094:28;44104:17;44094:28;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;44094:9:0;;-1:-1:-1;;44094:28:0:i;:::-;44129:20;44152:26;;;:17;:26;;;;;:36;44076:46;;-1:-1:-1;;;;;;44152:36:0;44203:26;;44195:64;;;;;-1:-1:-1;;;44195:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;44274:21:0;;44266:57;;;;;-1:-1:-1;;;44266:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;44330:26;;;;:17;:26;;;;;:46;;-1:-1:-1;;;;;;44330:46:0;-1:-1:-1;;;;;44330:46:0;;;;;-1:-1:-1;44383:32:0;:41;;;44502:9;44494:17;;;44486:97;;;;-1:-1:-1;;;44486:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44590:26;;;;:17;:26;;;;;;;;;:45;;-1:-1:-1;;;;;44590:45:0;-1:-1:-1;;;;;;;;44590:45:0;;;;;;44647:34;;;;;;;;;;;;;;;;;;;;;;;;43928:759;;;;;;:::o;30029:360::-;30065:324;30029:360;:::o;52299:242::-;53626:10;53607:30;;;;:18;:30;;;;;;52391:7;;53607:41;-1:-1:-1;53607:41:0;53599:86;;;;;-1:-1:-1;;;53599:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52462:10:::1;52443:30;::::0;;;:18:::1;:30;::::0;;;;;:43:::1;::::0;52478:7;52443:43:::1;:34;:43;:::i;:::-;52429:10;52410:30;::::0;;;:18:::1;:30;::::0;;;;;;;:76;;;;52500:4;;:34;;-1:-1:-1;;;52500:34:0;;-1:-1:-1;;;;;52500:34:0;;::::1;::::0;;::::1;::::0;;;;;;;;;;;;:4;::::1;::::0;:13:::1;::::0;:34;;;;;;;;;;;;;:4;:34;::::1;;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;52500:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;52500:34:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;52500:34:0;52493:42:::1;;;;52299:242:::0;;;:::o;50152:1916::-;50233:22;50257:24;;:::i;:::-;50676:13;;50290:17;;;;50516:19;;50676:32;;50668:63;;;;;-1:-1:-1;;;50668:63:0;;;;;;;;;;;;-1:-1:-1;;;50668:63:0;;;;;;;;;;;;;;;50738:27;;:::i;:::-;-1:-1:-1;50958:14:0;50946:27;;50940:34;51000:28;;;50994:35;50903:17;50891:30;;;50940:34;51059:20;50891:30;51059:9;:20::i;:::-;51042:37;;51098:38;51112:14;51128:7;51098:13;:38::i;:::-;51154:20;;;;:9;:20;;;;;;;;;51143:31;;;;;;;;;-1:-1:-1;;;;;51143:31:0;;;;;-1:-1:-1;;;51143:31:0;;;-1:-1:-1;;;;;51143:31:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;51154:20:0;;-1:-1:-1;51181:76:0;;;;;-1:-1:-1;;;51181:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;51310:42;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;51310:42:0;;;;;;51300:53;;;;;51272:24;;;;:81;51264:120;;;;;-1:-1:-1;;;51264:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;51413:19;;51443:23;51439:162;;51489:14;;:37;;;-1:-1:-1;;;51489:37:0;;;;;;;;;;-1:-1:-1;;;;;51489:14:0;;;;:27;;:37;;;;;;;;;;;;;;;:14;:37;;;2:2:-1;;;;27:1;24;17:12;2:2;51489:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;51489:37:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;51489:37:0;;-1:-1:-1;51543:23:0;51535:58;;;;;-1:-1:-1;;;51535:58:0;;;;;;;;;;;;-1:-1:-1;;;51535:58:0;;;;;;;;;;;;;;;51723:36;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;51723:36:0;;;;;;;51713:47;;;;;51915:14;51903:27;;51896:47;;;51966:12;51951:28;;52005:35;51907:6;52005:27;:35::i;:::-;51992:48;;50152:1916;;;;;;;;;;;:::o;960:167::-;1018:7;1046:5;;;1066:6;;;;1058:46;;;;;-1:-1:-1;;;1058:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;1120:1;-1:-1:-1;960:167:0;;;;;:::o;48733:1413::-;49050:86;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;49050:86:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;49006:17:0;;49422:6;;49443:9;:14;;49435:54;;;;;-1:-1:-1;;;49435:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;49922:12;49939:16;-1:-1:-1;;;;;49939:21:0;49961:4;49939:27;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;49939:27:0;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;-1:-1;;;;;;;;;;48733:1413:0:o;46372:988::-;53140:27;;;;:17;:27;;;;;:31;46534:8;;53140:27;;-1:-1:-1;;;53140:31:0;;-1:-1:-1;;;;;53140:31:0;53128:43;;;53120:76;;;;;-1:-1:-1;;;53120:76:0;;;;;;;;;;;;-1:-1:-1;;;53120:76:0;;;;;;;;;;;;;;;46564:13:::1;46580:16:::0;;;:6:::1;:16;::::0;;;;;;;-1:-1:-1;;;;;46580:25:0;::::1;::::0;;;;;;;;;46630:57:::1;46587:8:::0;46657:13;46597:7;46580:25;46630:16:::1;:57::i;:::-;46612:75;;46694:17;46714:32;46728:8;46738:7;46714:13;:32::i;:::-;46887:1;46838:20:::0;;;:9:::1;:20;::::0;;;;:37;46694:52;;-1:-1:-1;;;;;;46838:37:0::1;:51:::0;46831:59:::1;;;;46897:20;::::0;;;:9:::1;:20;::::0;;;;:47;;-1:-1:-1;;;;;;46897:47:0::1;-1:-1:-1::0;;;;;46897:47:0;::::1;;::::0;;46969:4:::1;46958:15:::0;::::1;46951:23;;;;47010:20;::::0;;;:9:::1;:20;::::0;;;;;;;:53;;-1:-1:-1;;;;;47010:53:0;::::1;-1:-1:-1::0;;;47010:53:0::1;-1:-1:-1::0;;;;;47010:53:0;;::::1;;::::0;;47119:47;;;;::::1;::::0;;;47153:12:::1;47119:47:::0;;;;;;26:21:-1;;;22:32;;6:49;;47119:47:0;;;;;;47109:58;;;;::::1;::::0;;;;-1:-1:-1;47070:36:0;;::::1;:97:::0;47216:27;;;:17:::1;:27:::0;;;;;;;:33;;::::1;::::0;47179:108;;;;;;;;;;;::::1;::::0;;;;;;;;;;;;;;;;;47216:33;;47179:108:::1;::::0;;;;;47010:53:::1;47179:108:::0;;::::1;47322:16;::::0;;;:6:::1;:16;::::0;;;;;;;-1:-1:-1;;;;;47322:25:0;::::1;::::0;;;;;;;;:32:::1;::::0;47352:1:::1;47322:32;:29;:32;:::i;:::-;47294:16;::::0;;;:6:::1;:16;::::0;;;;;;;-1:-1:-1;;;;;47294:25:0;;::::1;::::0;;;;;;;;;:60;;;;-1:-1:-1;;;;;;;46372:988:0:o;1390:170::-;1448:7;1477:1;1472;:6;;1464:49;;;;;-1:-1:-1;;;1464:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1532:5:0;;;1390:170::o;33489:174::-;33615:41;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;33615:41:0;;;;;;33605:52;;;;;;33489:174::o;31005:1024::-;31086:14;30065:324;31119:5;:12;:28;31111:59;;;;;-1:-1:-1;;;31111:59:0;;;;;;;;;;;;-1:-1:-1;;;31111:59:0;;;;;;;;;;;;;;;31181:20;;:::i;:::-;31255:23;;:::i;:::-;31366:24;;:::i;:::-;31399:16;31424:31;;:::i;:::-;31464:30;;:::i;:::-;31503:12;31612:5;31591:124;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;31591:124:0;;;;;;;;;;-1:-1:-1;31591:124:0;;;;-1:-1:-1;31591:124:0;;;;-1:-1:-1;31591:124:0;-1:-1:-1;31591:124:0;;;;-1:-1:-1;31591:124:0;;;;-1:-1:-1;31591:124:0;-1:-1:-1;31724:211:0;31591:124;;;31785:1;31778:9;;;;31803:6;31810:1;31803:9;;;;31828:6;31835:1;31828:9;;;;31856:8;31875:13;31899:12;31922:4;31724:14;:211::i;:::-;29951:1;32013:5;31971:48;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;31971:48:0;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;31971:48:0;;;31961:59;;;;;;31953:68;;31944:77;;31005:1024;;;;;;;;;;:::o;32862:236::-;33039:51;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;33039:51:0;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;33039:51:0;;;;;;33029:62;;;;;;32862:236::o;28221:1547::-;28477:13;28487:2;28477:9;:13::i;:::-;28469:52;;;;;-1:-1:-1;;;28469:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;28538:16;28548:5;28538:9;:16::i;:::-;28530:50;;;;;-1:-1:-1;;;28530:50:0;;;;;;;;;;;;-1:-1:-1;;;28530:50:0;;;;;;;;;;;;;;;28597:24;28607:13;28597:9;:24::i;:::-;28589:66;;;;;-1:-1:-1;;;28589:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;28672:23;28682:12;28672:9;:23::i;:::-;28664:64;;;;;-1:-1:-1;;;28664:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;29137:56;29174:1;29177:2;29181:1;29184:8;29137:36;:56::i;:::-;29119:122;;;;;-1:-1:-1;;;29119:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;29338:22;;:::i;:::-;29363:21;29375:2;29379:4;29363:11;:21::i;:::-;29338:46;;29478:19;;:::i;:::-;29500:81;29528:1;29531:5;29538:13;29553:1;29556:4;29562:12;29576:4;29500:17;:81::i;:::-;29478:103;;29642:16;29661:51;29683:4;29689:2;29693:5;29700:8;29710:1;29661:21;:51::i;:::-;29642:70;;29734:8;29729:1;:13;29721:39;;;;;-1:-1:-1;;;29721:39:0;;;;;;;;;;;;-1:-1:-1;;;29721:39:0;;;;;;;;;;;;;;;28221:1547;;;;;;;;;;;;:::o;14798:137::-;14912:4;;;;14861;;-1:-1:-1;;12681:66:0;14912:4;14899:30;14881:14;14890:1;14892;14890:4;;;;;14881:8;:14::i;:::-;:48;;14798:137;-1:-1:-1;;14798:137:0:o;24204:1060::-;24346:4;-1:-1:-1;;;;;24436:23:0;;24428:47;;;;;-1:-1:-1;;;24428:47:0;;;;;;;;;;;;-1:-1:-1;;;24428:47:0;;;;;;;;;;;;;;;24495:4;;;;24484:7;;24495:8;;:13;24494:25;;24517:2;24494:25;;;24512:2;24494:25;24484:35;-1:-1:-1;24557:18:0;-1:-1:-1;;24613:1:0;24607;24609;24607:4;;;;24600:28;24693:4;;-1:-1:-1;;24586:42:0;;;;-1:-1:-1;24578:51:0;;12443:66;24690:1;24683:28;25196:4;;25163:56;;;24675:37;25163:56;;;25196:4;25163:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24675:37;;-1:-1:-1;24675:37:0;;25163:56;;;;;;;25196:4;;-1:-1:-1;;25163:56:0;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;25163:56:0;;-1:-1:-1;;25163:56:0;;-1:-1:-1;;;;;25235:21:0;;;;;;;;-1:-1:-1;;;;;;24204:1060:0;;;;;;:::o;17020:376::-;17106:20;;:::i;:::-;17142:138;16230:1;17269:2;17273:5;17169:110;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;17169:110:0;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;17169:110:0;;;17142:26;:138::i;:::-;17137:143;;17289:100;17297:13;17307:2;17297:9;:13::i;:::-;17289:100;;17372:5;;17355:23;;;17372:5;17355:23;;;;;;;;;26:21:-1;;;22:32;;;6:49;;17355:23:0;;;;17328:51;;:26;:51::i;:::-;17323:56;;17289:100;;25756:582;25967:17;;:::i;:::-;26020:13;;26004;;-1:-1:-1;;12681:66:0;26004:29;;26003:44;25995:107;;;;;-1:-1:-1;;;25995:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;26119:30;26131:2;26135:1;26138:10;26119:11;:30::i;:::-;26111:76;;;;-1:-1:-1;;;26111:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26204:30;26216:2;26220:1;26223:10;26204:11;:30::i;:::-;26196:77;;;;-1:-1:-1;;;26196:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26289:41;26301:10;26313;26325:4;26289:11;:41::i;:::-;26282:48;25756:582;-1:-1:-1;;;;;;;;25756:582:0:o;27262:365::-;27442:9;26530:1;27588:4;27594:2;27598:5;27605:1;27608:8;27497:120;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;27497:120:0;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;27497:120:0;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;27497:120:0;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;27497:120:0;;;;;;;-1:-1:-1;;;;;27497:120:0;-1:-1:-1;;;;;27497:120:0;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;27497:120:0;;;27487:131;;;;;;27469:150;;27462:157;;27262:365;;;;;;;:::o;14496:263::-;14548:7;;-1:-1:-1;;12681:66:0;14683:1;14680;14673:24;14670:1;14663:47;14646:64;-1:-1:-1;;;14739:1:0;14731:6;14724:29;14717:36;14496:263;-1:-1:-1;;;14496:263:0:o;15817:251::-;15897:19;;:::i;:::-;15934:12;15944:1;15934:9;:12::i;:::-;15927:19;;15962:26;15973:14;15927:1;15929;15982:4;;15973:14;15962:10;:26::i;:::-;15955:4;;;:33;;;16008:1;;16001:8;16013:1;16001:13;15997:64;;;16047:4;;;;;-1:-1:-1;;16034:17:0;16027:24;;16047:1;15817:251;-1:-1:-1;15817:251:0:o;17900:993::-;18023:13;18056:11;18048:20;;12:1:-1;9;2:12;18048:20:0;18126:15;;;18188;;;18114:9;;18188:19;;:24;:34;;18220:2;18188:34;;;18215:2;18188:34;18178:44;-1:-1:-1;18576:20:0;-1:-1:-1;;18622:1:0;18614:6;18607:30;18662:50;;;18599:39;18662:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18599:39;;-1:-1:-1;18599:39:0;18662:50;;;;;;;;;-1:-1:-1;;18662:50:0;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18662:50:0;;;;;;;;18645:67;;18780:16;18842:7;18825:25;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;18825:25:0;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;18825:25:0;;;18815:36;;;;;;18807:45;;18780:73;;18878:8;-1:-1:-1;;;;;18868:18:0;:6;-1:-1:-1;;;;;18868:18:0;;18860:27;;;;;;;17900:993;;;;;:::o;23551:530::-;23664:17;;:::i;:::-;23766:5;;;23773;;;;23780;;23787;;;;23690:9;;;;;;23750:43;;23773:5;;23780;23750:15;:43::i;:::-;23738:55;;-1:-1:-1;23738:55:0;-1:-1:-1;23738:55:0;-1:-1:-1;;;23818:4:0;23815:1;23808:27;23839:1;23808:32;23800:70;;;;;-1:-1:-1;;;23800:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;24010:65;;;;;;;;-1:-1:-1;;24018:27:0;;;;;24028:4;24025:1;24018:27;24010:65;;;;-1:-1:-1;;24057:4:0;24054:1;24047:27;24010:65;;;23551:530;-1:-1:-1;;;;;;;23551:530:0:o;14993:402::-;15083:12;;;;;;15303:87;-1:-1:-1;;15310:2:0;:16;15303:87;;15360:20;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;15360:20:0;;;;;;15350:31;;;;;15303:87;;14326:107;14380:7;14403:24;14413:1;-1:-1:-1;;;;;14403:9:0;:24::i;21239:2034::-;21339:10;;;22093:1;;21339:10;-1:-1:-1;;22215:2:0;-1:-1:-1;;22202:15:0;22198:2;22191:39;22178:52;-1:-1:-1;22239:10:0;-1:-1:-1;;22276:2:0;-1:-1:-1;;22263:15:0;22259:2;22252:39;22239:52;;22302:10;22418:29;22432:2;22436;22440;22444;22418:13;:29::i;:::-;22407:40;;-1:-1:-1;22407:40:0;-1:-1:-1;22490:29:0;22407:40;;22512:2;22516;22490:13;:29::i;:::-;22479:40;;-1:-1:-1;22479:40:0;-1:-1:-1;22565:29:0;22479:40;;22587:2;22591;22565:13;:29::i;:::-;22554:40;;-1:-1:-1;22554:40:0;-1:-1:-1;22634:10:0;22752:29;22766:2;22770;22554:40;;22752:13;:29::i;:::-;22741:40;;-1:-1:-1;22741:40:0;-1:-1:-1;22810:29:0;22741:40;;22832:2;22836;22810:13;:29::i;:::-;22799:40;;-1:-1:-1;22799:40:0;-1:-1:-1;22887:29:0;22799:40;;22909:2;22913;22887:13;:29::i;:::-;22876:40;;-1:-1:-1;22876:40:0;-1:-1:-1;22962:8:0;;;22958:308;;-1:-1:-1;;23061:2:0;23057;23050:26;23045:31;-1:-1:-1;;;23103:2:0;23099;23092:26;23087:31;-1:-1:-1;;;23145:2:0;23141;23134:26;23129:31;;22958:308;;;23254:2;23249:7;;22958:308;21239:2034;;;;;;;;;;;;;;:::o;12925:1095::-;13004:22;13037:18;13064:41;;:::i;:::-;12797:4;13114:46;;;13188:26;;;:46;;;13266:26;;;:46;13343:26;;;:33;;;13385:26;;;:37;;;-1:-1:-1;;13431:26:0;;;:39;13479:24;;:::i;:::-;13857:4;13840:6;13764:4;13730:23;13665:4;-1:-1:-1;;13587:332:0;13573:346;-1:-1:-1;13940:15:0;13936:52;;13958:28;;;-1:-1:-1;;;13958:28:0;;;;;;;;;;;;-1:-1:-1;;;13958:28:0;;;;;;;;;;;;;;13936:52;14003:9;;;-1:-1:-1;;;;;12925:1095:0:o;19398:206::-;19496:10;;-1:-1:-1;;19552:2:0;19548;19541:26;-1:-1:-1;;19580:2:0;19576;19569:26;19529:67;;;;-1:-1:-1;19398:206:0;-1:-1:-1;;;;;19398:206:0:o;18986:323::-;19084:10;;;-1:-1:-1;;19143:2:0;19139;19132:26;19117:41;-1:-1:-1;19167:12:0;-1:-1:-1;;19206:2:0;19202;-1:-1:-1;;19189:15:0;19182:39;19167:54;-1:-1:-1;;;19255:4:0;19249;19242:30;-1:-1:-1;;19285:2:0;19281;19274:26;19230:71;;;;-1:-1:-1;18986:323:0;-1:-1:-1;;;;;;;18986:323:0:o;41366:12338::-;;;;;;;;;-1:-1:-1;41366:12338:0;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;-1:-1;41366:12338:0;;;-1:-1:-1;;41366:12338:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;-1:-1;41366:12338:0;;;-1:-1:-1;;41366:12338:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;-1:-1;41366:12338:0;;;-1:-1:-1;;41366:12338:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;-1:-1;41366:12338:0;;;-1:-1:-1;;41366:12338:0:o
Swarm Source
ipfs://161162074d9bf07615abb7876be2741cd4650817f75243f60750bea841412fa6
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|