Contract 0x8c7382f9d8f56b33781fe506e897a4f1e2d17255

Contract Overview

Balance:
0 MATIC

Token:
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xcb0e1cbc0feb2a07a41254a4c9a1d607b0cfdc0181645ddfeb234a79b943259aFulfill Randomne...192377802021-09-22 4:25:521 min ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.000265347
0x3c90f9ecf82f666c5a3241e6bee5e25d367f3d5a47a5b27280668ae9ae6e9846Fulfill Randomne...192373892021-09-22 4:12:2614 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.00160554
0xb1755c65bc6f2797437721d3bd9c9c17e14077501f601a63bad0662bdbe7b402Fulfill Randomne...192367142021-09-22 3:49:1237 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.0002247
0x17a722ccf3544269ae3c7ccf770c863ca56b0e6f57b033d3db3319f7bd751b10Fulfill Randomne...192365482021-09-22 3:43:3243 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.000276438
0xfe4393beced953ab615b00bc2da0044adc08dc1779f22a4f5e334ecd8ac812feFulfill Randomne...192364942021-09-22 3:41:4045 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.00030621
0xf4fe96af20302acd0a50ab76682f6e99fa9b98c7c48f94fca1647aced73781ffFulfill Randomne...192314342021-09-22 0:47:443 hrs 39 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.000320982
0x9157fa0196c1247a7cda69fb7488e0c81855e45069f9db15c1334a610d752106Fulfill Randomne...192311092021-09-22 0:36:343 hrs 50 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.000321024
0xa61304e0a06376161331d472a78a070b1069da105a4781c9122ecb7c5fb81fa8Fulfill Randomne...192310032021-09-22 0:32:543 hrs 54 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.000158703
0x8d23c0dc7e5f9a11ad49f8025bf25aabdf4420318fd50f0435eddb99991ed60aFulfill Randomne...192305632021-09-22 0:17:464 hrs 9 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.0009497
0xc2ef6eb7d2226f5a6c42c2bf54ae036186bbe7ec8aa733e43ca9db98aa205c9cFulfill Randomne...192304842021-09-22 0:15:044 hrs 11 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.0008986
0xe0bd86d15245a7b34a3c20963b44a9db99c23d5a8c7e56cf6d0f8e865377ea8aFulfill Randomne...192304072021-09-22 0:12:264 hrs 14 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.0010034
0x19b78685c5af91ddcc97d749fcc327bea49100620b0ea19b3221bffea502a417Fulfill Randomne...192280932021-09-21 22:52:505 hrs 34 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.000224127
0x8105c45755bd34a0a065347a9e4fc85f55049d802f2b2713c1202a929298c959Fulfill Randomne...192280882021-09-21 22:52:405 hrs 34 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.00020778
0xa836d993c372d5392dccba18d2283aae06abbbafb8b79099f2769dc4daa0c03cFulfill Randomne...192280882021-09-21 22:52:405 hrs 34 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.000207837
0xe3dd85ca36daa1a35bace3456f79255fd90577fb5d0530b19bd7c4bd62370a81Fulfill Randomne...192280882021-09-21 22:52:405 hrs 34 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.000207873
0xe99bbe883bda7f5f13dfea7f90a8ebd14267a0d2ecfcbe183e0038419c355fd9Fulfill Randomne...192280882021-09-21 22:52:405 hrs 34 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.00021582
0xa2356eea64e082434954f803106ee9bab1295ca9bd4ee83fa34ea47591cbe716Fulfill Randomne...192280782021-09-21 22:52:205 hrs 34 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.00021582
0x9eb536a6e272c881dd91daf5543bb0f2f06cf50016f4bcbbb95e0ee3a1c1be2fFulfill Randomne...192275162021-09-21 22:33:005 hrs 53 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.0008276435
0x5aa24e2eb87b78d478cb443a9b2c44c92c80e2a7dc18597c9558dd42ed06dfb3Fulfill Randomne...192275042021-09-21 22:32:365 hrs 54 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.000796375
0x9d44b367a42b82181c4859b9adda37e5d3a6fe02b2fe5814a6d219748c0201d4Fulfill Randomne...192275042021-09-21 22:32:365 hrs 54 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.0008276665
0xd8929548b1780ad14dabcb813760e04da42d09ab07d463d2196ca131b626703dFulfill Randomne...192275002021-09-21 22:32:285 hrs 54 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.00138554
0xb095106cd0487900ea01eaa01da99da4e08b70a83dda9fbb974d1ad652a7fe59Fulfill Randomne...192275002021-09-21 22:32:285 hrs 54 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.0013852
0xd8ce58340986f7b337ed369a9cb16b0822235aca4edf8303036feb59c542c0c8Fulfill Randomne...192274942021-09-21 22:32:165 hrs 54 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.0014387
0xd6ccc9b47f160c0bd67b26db74bdb524856018d98db5c9f50caf1ac03f9d4d09Fulfill Randomne...192272702021-09-21 22:24:366 hrs 2 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.00190725
0xdd91a7aacdf9bb74f92f07aae53efeaf3626b32deab0ecec99ce68396e811160Fulfill Randomne...192272062021-09-21 22:22:246 hrs 4 mins ago0xd332f54a0b97b43522c52cb2cfc66760b359a750 IN  0x8c7382f9d8f56b33781fe506e897a4f1e2d172550 MATIC0.00013473
[ Download CSV Export 
Latest 17 internal transactions
Parent Txn Hash Block From To Value
0x15622fe40440b3d39c284d41851cfbab9d828e5d30a95f0777f9280946a80b0c149426892021-06-10 22:03:36103 days 6 hrs ago 0xb89c32d84da0d610fb024576ac24247f0067c41e 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.05 MATIC
0x9ba4b0f2266e7bb95010ab1fd3fa7e731ff02d13c76d217186d9b95a59c6b0df149424032021-06-10 21:53:48103 days 6 hrs ago 0xb89c32d84da0d610fb024576ac24247f0067c41e 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.15 MATIC
0x44961ab4b7de136ad3398a75014702ad50787ab2b245d706c63a7cf335831e6d149421242021-06-10 21:44:10103 days 6 hrs ago 0xb89c32d84da0d610fb024576ac24247f0067c41e 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.15 MATIC
0x4d02dcadba703e739ce5751bdf1851125160134ca2b4952e74e2139335d23e7f149416962021-06-10 21:29:30103 days 6 hrs ago 0x6b8ab05eab76068a7ce7681b051c6487e83a1051 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.15 MATIC
0x556e469a3c0655bd49c2574371e9f8ca39ad7b21056560f7542874a4e55c854c149416382021-06-10 21:27:30103 days 6 hrs ago 0x6b8ab05eab76068a7ce7681b051c6487e83a1051 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.15 MATIC
0x55bfde51d970d48d8fde49cc17c146a8f2feb714c731334e883002c11312a17e149411752021-06-10 21:11:32103 days 7 hrs ago 0x42a2f6d30df528c383ade018d7526caf76b86db2 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.2 MATIC
0x94aa086ba31319ae43ae64cd065402615b245f3b20e05c71bed2b05452fdbd97149408922021-06-10 21:01:50103 days 7 hrs ago 0x7af24c3fdb74e75c3c7751629c0c72785fdf3daa 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.3 MATIC
0xd85e48be42ec3709f458fef51201c54da12ce64102d9361a9f7f8c19c6ba443d149402482021-06-10 20:39:42103 days 7 hrs ago 0xac577c5f7c6e769c47fe2780b390dfc483329fff 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.04 MATIC
0xd324d7da833ce200851ba634f6c2c355c87d5989d3b1386120eb712a358c2a2b149401822021-06-10 20:37:26103 days 7 hrs ago 0xac577c5f7c6e769c47fe2780b390dfc483329fff 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.04 MATIC
0xd2260b74120bb8e9879e1573964489421ee5411d3697b81985b851648d7f4a67149399202021-06-10 20:28:26103 days 7 hrs ago 0xac577c5f7c6e769c47fe2780b390dfc483329fff 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.12 MATIC
0x6bf5277923d903b6a4335fe4e1d3286694cfb6b0480b7e5a4307eafdb9719aa1149397872021-06-10 20:23:52103 days 8 hrs ago 0xac577c5f7c6e769c47fe2780b390dfc483329fff 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.04 MATIC
0x0b75ec9fd7bbc68372ec5e3667db8857ebfcacdbccd90d5752c2af914e0ca63e149393542021-06-10 20:08:58103 days 8 hrs ago 0x097b059b9e54980cf1654381ee3a2ee413fc94c9 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.04 MATIC
0x97a39b8330b5c57ef407ee2a3c8a31af87b5c76be26f0d8cfbf892e05ef5c3e4149391952021-06-10 20:03:28103 days 8 hrs ago 0x097b059b9e54980cf1654381ee3a2ee413fc94c9 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.12 MATIC
0x2f46220d42673cae5f30c634ed8098481bd97396eb6c721443f7e534e9363a7e149389822021-06-10 19:56:10103 days 8 hrs ago 0x097b059b9e54980cf1654381ee3a2ee413fc94c9 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.12 MATIC
0x6d8b34528373101b20c2e1d569da1202069ffe720592620afaf50cdd93f27d6e149388802021-06-10 19:52:42103 days 8 hrs ago 0x097b059b9e54980cf1654381ee3a2ee413fc94c9 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.04 MATIC
0xde36142455242d22a0d16437e4d6aa1374b01aa404e65eede14b5a7a98d5ada8149386502021-06-10 19:43:32103 days 8 hrs ago 0x097b059b9e54980cf1654381ee3a2ee413fc94c9 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.04 MATIC
0x0fdb15d4a6de7dd48d5f0e895a57891c326c48f51689c58b61042158aa43ce63149377392021-06-10 19:11:20103 days 9 hrs ago 0x097b059b9e54980cf1654381ee3a2ee413fc94c9 0x8c7382f9d8f56b33781fe506e897a4f1e2d172550.03 MATIC
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
VRFCoordinator

Compiler Version
v0.6.6+commit.6c089d02

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

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");
    _;
  }

}

Contract ABI

[{"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"}]

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
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading