From 14d46fa46a6643551e2a1ed7037776bb35a0d529 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 6 Dec 2024 23:01:19 +0000 Subject: [PATCH 01/12] feat: chainlink rng, updated randomizer rng for consistency --- .../deploy/00-home-chain-arbitration-neo.ts | 16 +- .../00-home-chain-arbitration-university.ts | 6 +- contracts/deploy/00-home-chain-arbitration.ts | 16 +- contracts/deploy/00-rng.ts | 9 +- contracts/package.json | 3 +- contracts/src/rng/ChainlinkRNG.sol | 173 ++++ contracts/src/rng/RandomizerRNG.sol | 54 +- cspell.json | 1 + yarn.lock | 776 +++++++++++++++++- 9 files changed, 1012 insertions(+), 42 deletions(-) create mode 100644 contracts/src/rng/ChainlinkRNG.sol diff --git a/contracts/deploy/00-home-chain-arbitration-neo.ts b/contracts/deploy/00-home-chain-arbitration-neo.ts index 4ce2c1213..ce4105f04 100644 --- a/contracts/deploy/00-home-chain-arbitration-neo.ts +++ b/contracts/deploy/00-home-chain-arbitration-neo.ts @@ -6,7 +6,7 @@ import { changeCurrencyRate } from "./utils/klerosCoreHelper"; import { HomeChains, isSkipped, isDevnet, PNK, ETH } from "./utils"; import { getContractOrDeploy, getContractOrDeployUpgradable } from "./utils/getContractOrDeploy"; import { deployERC20AndFaucet, deployERC721 } from "./utils/deployTokens"; -import { DisputeKitClassic, KlerosCoreNeo } from "../typechain-types"; +import { DisputeKitClassic, KlerosCoreNeo, RandomizerRNG } from "../typechain-types"; const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const { ethers, deployments, getNamedAccounts, getChainId } = hre; @@ -38,7 +38,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const rng = await deployUpgradable(deployments, "RandomizerRNG", { from: deployer, - args: [randomizerOracle.target, deployer], + args: [deployer, ZeroAddress, randomizerOracle.target], // The SortitionModule is configured later log: true, }); @@ -85,7 +85,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) deployer, deployer, pnk.target, - ZeroAddress, + ZeroAddress, // KlerosCore is configured later disputeKit.address, false, [minStake, alpha, feeForJuror, jurorsForCourtJump], @@ -97,7 +97,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) log: true, }); // nonce+2 (implementation), nonce+3 (proxy) - // execute DisputeKitClassic.changeCore() only if necessary + // disputeKit.changeCore() only if necessary const disputeKitContract = (await hre.ethers.getContract("DisputeKitClassicNeo")) as DisputeKitClassic; const currentCore = await disputeKitContract.core(); if (currentCore !== klerosCore.address) { @@ -105,6 +105,14 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) await disputeKitContract.changeCore(klerosCore.address); } + // rng.changeSortitionModule() only if necessary + const rngContract = (await ethers.getContract("RandomizerRNG")) as RandomizerRNG; + const currentSortitionModule = await rngContract.sortitionModule(); + if (currentSortitionModule !== sortitionModule.address) { + console.log(`rng.changeSortitionModule(${sortitionModule.address})`); + await rngContract.changeSortitionModule(sortitionModule.address); + } + const core = (await hre.ethers.getContract("KlerosCoreNeo")) as KlerosCoreNeo; try { await changeCurrencyRate(core, await weth.getAddress(), true, 1, 1); diff --git a/contracts/deploy/00-home-chain-arbitration-university.ts b/contracts/deploy/00-home-chain-arbitration-university.ts index de399db6e..218e498b9 100644 --- a/contracts/deploy/00-home-chain-arbitration-university.ts +++ b/contracts/deploy/00-home-chain-arbitration-university.ts @@ -5,7 +5,7 @@ import { deployUpgradable } from "./utils/deployUpgradable"; import { changeCurrencyRate } from "./utils/klerosCoreHelper"; import { ETH, HomeChains, PNK, isSkipped } from "./utils"; import { deployERC20AndFaucet } from "./utils/deployTokens"; -import { DisputeKitClassic, KlerosCore, KlerosCoreUniversity } from "../typechain-types"; +import { DisputeKitClassic, KlerosCoreUniversity } from "../typechain-types"; import { getContractOrDeploy, getContractOrDeployUpgradable } from "./utils/getContractOrDeploy"; const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { @@ -53,7 +53,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) deployer, // governor deployer, // instructor pnk.target, - ZeroAddress, + ZeroAddress, // KlerosCore is configured later disputeKit.address, false, [minStake, alpha, feeForJuror, jurorsForCourtJump], @@ -63,7 +63,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) log: true, }); // nonce+2 (implementation), nonce+3 (proxy) - // changeCore() only if necessary + // disputeKit.changeCore() only if necessary const disputeKitContract = (await ethers.getContract("DisputeKitClassicUniversity")) as DisputeKitClassic; const currentCore = await disputeKitContract.core(); if (currentCore !== klerosCore.address) { diff --git a/contracts/deploy/00-home-chain-arbitration.ts b/contracts/deploy/00-home-chain-arbitration.ts index e2093bf4c..b1cc2c6b7 100644 --- a/contracts/deploy/00-home-chain-arbitration.ts +++ b/contracts/deploy/00-home-chain-arbitration.ts @@ -6,7 +6,7 @@ import { changeCurrencyRate } from "./utils/klerosCoreHelper"; import { HomeChains, isSkipped, isDevnet, isMainnet, PNK, ETH } from "./utils"; import { getContractOrDeploy, getContractOrDeployUpgradable } from "./utils/getContractOrDeploy"; import { deployERC20AndFaucet } from "./utils/deployTokens"; -import { DisputeKitClassic, KlerosCore } from "../typechain-types"; +import { DisputeKitClassic, KlerosCore, RandomizerRNG } from "../typechain-types"; const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const { ethers, deployments, getNamedAccounts, getChainId } = hre; @@ -38,7 +38,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const randomizerRng = await getContractOrDeployUpgradable(hre, "RandomizerRNG", { from: deployer, - args: [randomizerOracle.target, deployer], + args: [deployer, ZeroAddress, randomizerOracle.target], // The SortitionModule is configured later log: true, }); @@ -83,7 +83,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) deployer, deployer, pnk.target, - ZeroAddress, + ZeroAddress, // KlerosCore is configured later disputeKit.address, false, [minStake, alpha, feeForJuror, jurorsForCourtJump], @@ -94,7 +94,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) log: true, }); // nonce+2 (implementation), nonce+3 (proxy) - // changeCore() only if necessary + // disputeKit.changeCore() only if necessary const disputeKitContract = (await ethers.getContract("DisputeKitClassic")) as DisputeKitClassic; const currentCore = await disputeKitContract.core(); if (currentCore !== klerosCore.address) { @@ -102,6 +102,14 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) await disputeKitContract.changeCore(klerosCore.address); } + // rng.changeSortitionModule() only if necessary + const rngContract = (await ethers.getContract("RandomizerRNG")) as RandomizerRNG; + const currentSortitionModule = await rngContract.sortitionModule(); + if (currentSortitionModule !== sortitionModule.address) { + console.log(`rng.changeSortitionModule(${sortitionModule.address})`); + await rngContract.changeSortitionModule(sortitionModule.address); + } + const core = (await hre.ethers.getContract("KlerosCore")) as KlerosCore; try { await changeCurrencyRate(core, await pnk.getAddress(), true, 12225583, 12); diff --git a/contracts/deploy/00-rng.ts b/contracts/deploy/00-rng.ts index 83d320b0b..269244ef9 100644 --- a/contracts/deploy/00-rng.ts +++ b/contracts/deploy/00-rng.ts @@ -1,7 +1,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; import { SortitionModule } from "../typechain-types"; -import { HomeChains, isSkipped } from "./utils"; +import { HomeChains, isMainnet, isSkipped } from "./utils"; import { deployUpgradable } from "./utils/deployUpgradable"; import { getContractOrDeploy } from "./utils/getContractOrDeploy"; @@ -15,6 +15,8 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const chainId = Number(await getChainId()); console.log("deploying to %s with deployer %s", HomeChains[chainId], deployer); + const sortitionModule = (await ethers.getContract("SortitionModuleNeo")) as SortitionModule; + const randomizerOracle = await getContractOrDeploy(hre, "RandomizerOracle", { from: deployer, contract: "RandomizerMock", @@ -24,7 +26,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const rng1 = await deployUpgradable(deployments, "RandomizerRNG", { from: deployer, - args: [randomizerOracle.address, deployer], + args: [deployer, sortitionModule.target, randomizerOracle.address], log: true, }); @@ -34,13 +36,12 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) log: true, }); - const sortitionModule = (await ethers.getContract("SortitionModuleNeo")) as SortitionModule; await sortitionModule.changeRandomNumberGenerator(rng2.address, RNG_LOOKAHEAD); }; deployArbitration.tags = ["RNG"]; deployArbitration.skip = async ({ network }) => { - return isSkipped(network, !HomeChains[network.config.chainId ?? 0]); + return isSkipped(network, isMainnet(network)); }; export default deployArbitration; diff --git a/contracts/package.json b/contracts/package.json index 913ccef8c..d9729185b 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -68,7 +68,6 @@ "@nomicfoundation/hardhat-chai-matchers": "^2.0.8", "@nomicfoundation/hardhat-ethers": "^3.0.8", "@nomiclabs/hardhat-solhint": "^4.0.1", - "@openzeppelin/contracts": "^5.1.0", "@typechain/ethers-v6": "^0.5.1", "@typechain/hardhat": "^9.1.0", "@types/chai": "^4.3.20", @@ -105,7 +104,9 @@ "typescript": "^5.6.3" }, "dependencies": { + "@chainlink/contracts": "^1.3.0", "@kleros/vea-contracts": "^0.4.0", + "@openzeppelin/contracts": "^5.1.0", "viem": "^2.21.48" } } diff --git a/contracts/src/rng/ChainlinkRNG.sol b/contracts/src/rng/ChainlinkRNG.sol new file mode 100644 index 000000000..41f2f770a --- /dev/null +++ b/contracts/src/rng/ChainlinkRNG.sol @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {VRFConsumerBaseV2Plus, IVRFCoordinatorV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; +import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; + +import "./RNG.sol"; + +/// @title Random Number Generator that uses Chainlink VRF v2.5 +/// https://blog.chain.link/introducing-vrf-v2-5/ +contract ChainlinkRNG is RNG, VRFConsumerBaseV2Plus { + // ************************************* // + // * Storage * // + // ************************************* // + + address public governor; // The address that can withdraw funds. + address public sortitionModule; // The address of the SortitionModule. + bytes32 public keyHash; // The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job). + uint256 public subscriptionId; // The unique identifier of the subscription used for funding requests. + uint16 public requestConfirmations; // How many confirmations the Chainlink node should wait before responding. + // 22 bytes remaining in slot + uint32 public callbackGasLimit; // Gas limit for the Chainlink callback. + uint256 lastRequestId; // The last request ID. + mapping(uint256 requestId => uint256 number) public randomNumbers; // randomNumbers[requestID] is the random number for this request id, 0 otherwise. + + // ************************************* // + // * Events * // + // ************************************* // + + /// @dev Emitted when a request is sent to the VRF Coordinator + /// @param requestId The ID of the request + event RequestSent(uint256 indexed requestId); + + /// Emitted when a request has been fulfilled. + /// @param requestId The ID of the request + /// @param randomWord The random value answering the request. + event RequestFulfilled(uint256 indexed requestId, uint256 randomWord); + + // ************************************* // + // * Function Modifiers * // + // ************************************* // + + modifier onlyByGovernor() { + require(governor == msg.sender, "Governor only"); + _; + } + + modifier onlyBySortitionModule() { + require(sortitionModule == msg.sender, "SortitionModule only"); + _; + } + + // ************************************* // + // * Constructor * // + // ************************************* // + + /// @dev Constructor, initializing the implementation to reduce attack surface. + /// @param _governor The Governor of the contract. + /// @param _sortitionModule The address of the SortitionModule contract. + /// @param _vrfCoordinator The address of the VRFCoordinator contract. + /// @param _keyHash The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job). + /// @param _subscriptionId The unique identifier of the subscription used for funding requests. + /// @param _requestConfirmations How many confirmations the Chainlink node should wait before responding. + /// @param _callbackGasLimit The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function. + /// @dev https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number + constructor( + address _governor, + address _sortitionModule, + address _vrfCoordinator, + bytes32 _keyHash, + uint256 _subscriptionId, + uint16 _requestConfirmations, + uint32 _callbackGasLimit + ) VRFConsumerBaseV2Plus(_vrfCoordinator) { + governor = _governor; + sortitionModule = _sortitionModule; + keyHash = _keyHash; + subscriptionId = _subscriptionId; + requestConfirmations = _requestConfirmations; + callbackGasLimit = _callbackGasLimit; + } + + // ************************************* // + // * Governance * // + // ************************************* // + + /// @dev Changes the governor of the contract. + /// @param _governor The new governor. + function changeGovernor(address _governor) external onlyByGovernor { + governor = _governor; + } + + /// @dev Changes the sortition module of the contract. + /// @param _sortitionModule The new sortition module. + function changeSortitionModule(address _sortitionModule) external onlyByGovernor { + sortitionModule = _sortitionModule; + } + + /// @dev Changes the VRF Coordinator of the contract. + /// @param _vrfCoordinator The new VRF Coordinator. + function changeVrfCoordinator(address _vrfCoordinator) external onlyByGovernor { + s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator); + emit CoordinatorSet(_vrfCoordinator); + } + + /// @dev Changes the key hash of the contract. + /// @param _keyHash The new key hash. + function changeKeyHash(bytes32 _keyHash) external onlyByGovernor { + keyHash = _keyHash; + } + + /// @dev Changes the subscription ID of the contract. + /// @param _subscriptionId The new subscription ID. + function changeSubscriptionId(uint256 _subscriptionId) external onlyByGovernor { + subscriptionId = _subscriptionId; + } + + /// @dev Changes the request confirmations of the contract. + /// @param _requestConfirmations The new request confirmations. + function changeRequestConfirmations(uint16 _requestConfirmations) external onlyByGovernor { + requestConfirmations = _requestConfirmations; + } + + /// @dev Changes the callback gas limit of the contract. + /// @param _callbackGasLimit The new callback gas limit. + function changeCallbackGasLimit(uint32 _callbackGasLimit) external onlyByGovernor { + callbackGasLimit = _callbackGasLimit; + } + + // ************************************* // + // * State Modifiers * // + // ************************************* // + + /// @dev Request a random number. SortitionModule only. + function requestRandomness(uint256 /*_block*/) external override onlyBySortitionModule { + // Will revert if subscription is not set and funded. + uint256 requestId = s_vrfCoordinator.requestRandomWords( + VRFV2PlusClient.RandomWordsRequest({ + keyHash: keyHash, + subId: subscriptionId, + requestConfirmations: requestConfirmations, + callbackGasLimit: callbackGasLimit, + numWords: 1, + extraArgs: VRFV2PlusClient._argsToBytes( + // Set nativePayment to true to pay for VRF requests with ETH instead of LINK + VRFV2PlusClient.ExtraArgsV1({nativePayment: true}) + ) + }) + ); + lastRequestId = requestId; + emit RequestSent(requestId); + } + + /// @dev Callback function called by the VRF Coordinator when the random value is generated. + /// @param _requestId The ID of the request. + /// @param _randomWords The random values answering the request. + function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) internal override { + // Access control is handled by the parent VRFCoordinator.rawFulfillRandomWords() + randomNumbers[_requestId] = _randomWords[0]; + emit RequestFulfilled(_requestId, _randomWords[0]); + } + + // ************************************* // + // * Public Views * // + // ************************************* // + + /// @dev Return the random number. + /// @return randomNumber The random number or 0 if it is not ready or has not been requested. + function receiveRandomness(uint256 /*_block*/) external view override returns (uint256 randomNumber) { + randomNumber = randomNumbers[lastRequestId]; + } +} diff --git a/contracts/src/rng/RandomizerRNG.sol b/contracts/src/rng/RandomizerRNG.sol index 4cb147804..6849247d6 100644 --- a/contracts/src/rng/RandomizerRNG.sol +++ b/contracts/src/rng/RandomizerRNG.sol @@ -15,10 +15,24 @@ contract RandomizerRNG is RNG, UUPSProxiable, Initializable { // ************************************* // address public governor; // The address that can withdraw funds. - uint256 public callbackGasLimit; // Gas limit for the randomizer callback + address public sortitionModule; // The address of the SortitionModule. IRandomizer public randomizer; // Randomizer address. + uint256 public callbackGasLimit; // Gas limit for the Randomizer.ai callback. + uint256 lastRequestId; // The last request ID. mapping(uint256 requestId => uint256 number) public randomNumbers; // randomNumbers[requestID] is the random number for this request id, 0 otherwise. - mapping(address requester => uint256 requestId) public requesterToID; // Maps the requester to his latest request ID. + + // ************************************* // + // * Events * // + // ************************************* // + + /// @dev Emitted when a request is sent to the VRF Coordinator + /// @param requestId The ID of the request + event RequestSent(uint256 indexed requestId); + + /// Emitted when a request has been fulfilled. + /// @param requestId The ID of the request + /// @param randomWords The random values answering the request. + event RequestFulfilled(uint256 indexed requestId, uint256 randomWords); // ************************************* // // * Function Modifiers * // @@ -29,6 +43,11 @@ contract RandomizerRNG is RNG, UUPSProxiable, Initializable { _; } + modifier onlyBySortitionModule() { + require(sortitionModule == msg.sender, "SortitionModule only"); + _; + } + // ************************************* // // * Constructor * // // ************************************* // @@ -41,9 +60,14 @@ contract RandomizerRNG is RNG, UUPSProxiable, Initializable { /// @dev Initializer /// @param _randomizer Randomizer contract. /// @param _governor Governor of the contract. - function initialize(IRandomizer _randomizer, address _governor) external reinitializer(1) { - randomizer = _randomizer; + function initialize( + address _governor, + address _sortitionModule, + IRandomizer _randomizer + ) external reinitializer(1) { governor = _governor; + sortitionModule = _sortitionModule; + randomizer = _randomizer; callbackGasLimit = 50000; } @@ -65,6 +89,12 @@ contract RandomizerRNG is RNG, UUPSProxiable, Initializable { governor = _governor; } + /// @dev Changes the sortition module of the contract. + /// @param _sortitionModule The new sortition module. + function changeSortitionModule(address _sortitionModule) external onlyByGovernor { + sortitionModule = _sortitionModule; + } + /// @dev Change the Randomizer callback gas limit. /// @param _callbackGasLimit the new limit. function setCallbackGasLimit(uint256 _callbackGasLimit) external onlyByGovernor { @@ -87,16 +117,20 @@ contract RandomizerRNG is RNG, UUPSProxiable, Initializable { // * State Modifiers * // // ************************************* // - /// @dev Request a random number. The id of the request is tied to the sender. - function requestRandomness(uint256 /*_block*/) external override { - uint256 id = randomizer.request(callbackGasLimit); - requesterToID[msg.sender] = id; + /// @dev Request a random number. SortitionModule only. + function requestRandomness(uint256 /*_block*/) external override onlyBySortitionModule { + uint256 requestId = randomizer.request(callbackGasLimit); + lastRequestId = requestId; + emit RequestSent(requestId); } /// @dev Callback function called by the randomizer contract when the random value is generated. + /// @param _id The ID of the request. + /// @param _value The random value answering the request. function randomizerCallback(uint256 _id, bytes32 _value) external { require(msg.sender == address(randomizer), "Randomizer only"); randomNumbers[_id] = uint256(_value); + emit RequestFulfilled(_id, uint256(_value)); } // ************************************* // @@ -106,8 +140,6 @@ contract RandomizerRNG is RNG, UUPSProxiable, Initializable { /// @dev Return the random number. /// @return randomNumber The random number or 0 if it is not ready or has not been requested. function receiveRandomness(uint256 /*_block*/) external view override returns (uint256 randomNumber) { - // Get the latest request ID for this requester. - uint256 id = requesterToID[msg.sender]; - randomNumber = randomNumbers[id]; + randomNumber = randomNumbers[lastRequestId]; } } diff --git a/cspell.json b/cspell.json index 2862030d1..c671ffe5b 100644 --- a/cspell.json +++ b/cspell.json @@ -15,6 +15,7 @@ "ARBSEPOLIA", "autorestart", "CHAINID", + "Chainlink", "codegen", "commify", "commitlint", diff --git a/yarn.lock b/yarn.lock index 31014172f..88af269f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -82,6 +82,46 @@ __metadata: languageName: node linkType: hard +"@arbitrum/nitro-contracts@npm:1.1.1": + version: 1.1.1 + resolution: "@arbitrum/nitro-contracts@npm:1.1.1" + dependencies: + "@offchainlabs/upgrade-executor": "npm:1.1.0-beta.0" + "@openzeppelin/contracts": "npm:4.5.0" + "@openzeppelin/contracts-upgradeable": "npm:4.5.2" + patch-package: "npm:^6.4.7" + checksum: 10/6ea79388bd8ed6de2fdb2e1334d37b520928732c86540eaebed1e21a9f2a04dbc11dbae89f06bd66a169130f9b54d90c9fe6ed45cd4d286bc28b4d77fd49c1f8 + languageName: node + linkType: hard + +"@arbitrum/nitro-contracts@npm:^1.0.0-beta.8": + version: 1.3.0 + resolution: "@arbitrum/nitro-contracts@npm:1.3.0" + dependencies: + "@offchainlabs/upgrade-executor": "npm:1.1.0-beta.0" + "@openzeppelin/contracts": "npm:4.5.0" + "@openzeppelin/contracts-upgradeable": "npm:4.5.2" + patch-package: "npm:^6.4.7" + checksum: 10/cc931bf6d65f8249cfe0527b5e7be2bfb30c40ea8408320949db76e20076b91dcbb384f5b5fb997f303f1b4b83310a0f98a5382d4ec1a58be8cf92267d615121 + languageName: node + linkType: hard + +"@arbitrum/token-bridge-contracts@npm:1.1.2": + version: 1.1.2 + resolution: "@arbitrum/token-bridge-contracts@npm:1.1.2" + dependencies: + "@arbitrum/nitro-contracts": "npm:^1.0.0-beta.8" + "@offchainlabs/upgrade-executor": "npm:1.1.0-beta.0" + "@openzeppelin/contracts": "npm:4.8.3" + "@openzeppelin/contracts-upgradeable": "npm:4.8.3" + "@openzeppelin/upgrades-core": "npm:^1.24.1" + dependenciesMeta: + "@openzeppelin/upgrades-core": + optional: true + checksum: 10/d9a1b69db886e4d34f34f9b92dc226ee2add122328da9dc79a4046322a486a731f5992b8e22a0929b1bb717f9d1d1b60b43085fb952a50e955447b3d7aa1bf0c + languageName: node + linkType: hard + "@ardatan/relay-compiler@npm:12.0.0": version: 12.0.0 resolution: "@ardatan/relay-compiler@npm:12.0.0" @@ -1920,6 +1960,31 @@ __metadata: languageName: node linkType: hard +"@bytecodealliance/preview2-shim@npm:0.17.0": + version: 0.17.0 + resolution: "@bytecodealliance/preview2-shim@npm:0.17.0" + checksum: 10/28a273227d8e8f2b61ad0260be612fd854ace756784c409c6ac4b65bf6b48426e6c058e45c07675303ef844a981fbdda7257df9833ca12bd3e5e4a0480ca5193 + languageName: node + linkType: hard + +"@chainlink/contracts@npm:^1.3.0": + version: 1.3.0 + resolution: "@chainlink/contracts@npm:1.3.0" + dependencies: + "@arbitrum/nitro-contracts": "npm:1.1.1" + "@arbitrum/token-bridge-contracts": "npm:1.1.2" + "@changesets/changelog-github": "npm:^0.5.0" + "@changesets/cli": "npm:~2.27.8" + "@eth-optimism/contracts": "npm:0.6.0" + "@openzeppelin/contracts": "npm:4.9.3" + "@openzeppelin/contracts-upgradeable": "npm:4.9.3" + "@scroll-tech/contracts": "npm:0.1.0" + "@zksync/contracts": "git+https://github.com/matter-labs/era-contracts.git#446d391d34bdb48255d5f8fef8a8248925fc98b9" + semver: "npm:^7.6.3" + checksum: 10/223e80492520cccad301ba360a27c11c73070cc8e9d03af73f68db987f9ad1e0a43f98e9feb8f284d68e9c79273647d3fadb7477532259de96840cfc67d2ebf3 + languageName: node + linkType: hard + "@chainsafe/is-ip@npm:^2.0.1": version: 2.0.1 resolution: "@chainsafe/is-ip@npm:2.0.1" @@ -1936,6 +2001,261 @@ __metadata: languageName: node linkType: hard +"@changesets/apply-release-plan@npm:^7.0.6": + version: 7.0.6 + resolution: "@changesets/apply-release-plan@npm:7.0.6" + dependencies: + "@changesets/config": "npm:^3.0.4" + "@changesets/get-version-range-type": "npm:^0.4.0" + "@changesets/git": "npm:^3.0.2" + "@changesets/should-skip-package": "npm:^0.1.1" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + detect-indent: "npm:^6.0.0" + fs-extra: "npm:^7.0.1" + lodash.startcase: "npm:^4.4.0" + outdent: "npm:^0.5.0" + prettier: "npm:^2.7.1" + resolve-from: "npm:^5.0.0" + semver: "npm:^7.5.3" + checksum: 10/98e6d87eed744e26bbca9032bad225a9c29da2189fa37d2cc3fa877b9e7e4dbb1860b56259faf426af470db445471e888ac26978e1380d96e9e917ab0c54259f + languageName: node + linkType: hard + +"@changesets/assemble-release-plan@npm:^6.0.5": + version: 6.0.5 + resolution: "@changesets/assemble-release-plan@npm:6.0.5" + dependencies: + "@changesets/errors": "npm:^0.2.0" + "@changesets/get-dependents-graph": "npm:^2.1.2" + "@changesets/should-skip-package": "npm:^0.1.1" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + semver: "npm:^7.5.3" + checksum: 10/0de3edde14ec1b61d767be5186d4e24e2330291b1e5e8b8c6fd4bda0b8d5d967cefd2c7e7ea790e4bce12920ffb32c6ab9eb74e82bf5f762c20428b321050175 + languageName: node + linkType: hard + +"@changesets/changelog-git@npm:^0.2.0": + version: 0.2.0 + resolution: "@changesets/changelog-git@npm:0.2.0" + dependencies: + "@changesets/types": "npm:^6.0.0" + checksum: 10/631fcb73cab584fefad30f0e7cc8f7624b36be0f199e526c0d53538da16df2776bef8f8eb6511247b8040d011a2582bdb4840275d3f90a046bacbbd717da6c83 + languageName: node + linkType: hard + +"@changesets/changelog-github@npm:^0.5.0": + version: 0.5.0 + resolution: "@changesets/changelog-github@npm:0.5.0" + dependencies: + "@changesets/get-github-info": "npm:^0.6.0" + "@changesets/types": "npm:^6.0.0" + dotenv: "npm:^8.1.0" + checksum: 10/a9c01d918f67c3d5dd38a505da29261518bed932c67fe3eb85cc15a485d32c1d11549cd276f121b4e169f26fb20923b435e931e6a5e83e213623dd8c3733cde9 + languageName: node + linkType: hard + +"@changesets/cli@npm:~2.27.8": + version: 2.27.10 + resolution: "@changesets/cli@npm:2.27.10" + dependencies: + "@changesets/apply-release-plan": "npm:^7.0.6" + "@changesets/assemble-release-plan": "npm:^6.0.5" + "@changesets/changelog-git": "npm:^0.2.0" + "@changesets/config": "npm:^3.0.4" + "@changesets/errors": "npm:^0.2.0" + "@changesets/get-dependents-graph": "npm:^2.1.2" + "@changesets/get-release-plan": "npm:^4.0.5" + "@changesets/git": "npm:^3.0.2" + "@changesets/logger": "npm:^0.1.1" + "@changesets/pre": "npm:^2.0.1" + "@changesets/read": "npm:^0.6.2" + "@changesets/should-skip-package": "npm:^0.1.1" + "@changesets/types": "npm:^6.0.0" + "@changesets/write": "npm:^0.3.2" + "@manypkg/get-packages": "npm:^1.1.3" + ansi-colors: "npm:^4.1.3" + ci-info: "npm:^3.7.0" + enquirer: "npm:^2.3.0" + external-editor: "npm:^3.1.0" + fs-extra: "npm:^7.0.1" + mri: "npm:^1.2.0" + p-limit: "npm:^2.2.0" + package-manager-detector: "npm:^0.2.0" + picocolors: "npm:^1.1.0" + resolve-from: "npm:^5.0.0" + semver: "npm:^7.5.3" + spawndamnit: "npm:^3.0.1" + term-size: "npm:^2.1.0" + bin: + changeset: bin.js + checksum: 10/a0d95aa88f88e952c34aba8f6a36cbc7bdeba60bdfbfb30704532d74eecfa8c0d97ec5f0d16c4ca4cac9d9a1b5f3b34e29dafd3fb183013ce35ccc0840e707e3 + languageName: node + linkType: hard + +"@changesets/config@npm:^3.0.4": + version: 3.0.4 + resolution: "@changesets/config@npm:3.0.4" + dependencies: + "@changesets/errors": "npm:^0.2.0" + "@changesets/get-dependents-graph": "npm:^2.1.2" + "@changesets/logger": "npm:^0.1.1" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + fs-extra: "npm:^7.0.1" + micromatch: "npm:^4.0.8" + checksum: 10/dc59f640bca8e4c88f76f187c8ca9ebae4cdf152559473da9a2193bc5f2ebb9c3709560a8c381855a14858ece63d23000e043ff01c82572fe053f3d13481b797 + languageName: node + linkType: hard + +"@changesets/errors@npm:^0.2.0": + version: 0.2.0 + resolution: "@changesets/errors@npm:0.2.0" + dependencies: + extendable-error: "npm:^0.1.5" + checksum: 10/4b79373f92287af4f723e8dbbccaf0299aa8735fc043243d0ad587f04a7614615ea50180be575d4438b9f00aa82d1cf85e902b77a55bdd3e0a8dd97e77b18c60 + languageName: node + linkType: hard + +"@changesets/get-dependents-graph@npm:^2.1.2": + version: 2.1.2 + resolution: "@changesets/get-dependents-graph@npm:2.1.2" + dependencies: + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + picocolors: "npm:^1.1.0" + semver: "npm:^7.5.3" + checksum: 10/36d9877b0b071183b253d894e0dbef56f764fe2ff592064489d4f122c419ab97f0d023c9e078849d0f48b4129f5018c7c81cb380b02d975db5e0768ab29226c1 + languageName: node + linkType: hard + +"@changesets/get-github-info@npm:^0.6.0": + version: 0.6.0 + resolution: "@changesets/get-github-info@npm:0.6.0" + dependencies: + dataloader: "npm:^1.4.0" + node-fetch: "npm:^2.5.0" + checksum: 10/4ba61eafb0a75fa7f741885b465d90559e63581e748527e060f90c37380a02f62810db3bc79a4e74d109754d7f72dc45249e1ac2be5fcaec6a7d0f99db1cee78 + languageName: node + linkType: hard + +"@changesets/get-release-plan@npm:^4.0.5": + version: 4.0.5 + resolution: "@changesets/get-release-plan@npm:4.0.5" + dependencies: + "@changesets/assemble-release-plan": "npm:^6.0.5" + "@changesets/config": "npm:^3.0.4" + "@changesets/pre": "npm:^2.0.1" + "@changesets/read": "npm:^0.6.2" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + checksum: 10/f6e7c59d78a8f57f46843153b1113ff312e10fdc61930752b399a2862259c17ea69c44a67fff84961a9c73ac74a7a3ae0cd409da8b41e8f8ccb2d331884627e4 + languageName: node + linkType: hard + +"@changesets/get-version-range-type@npm:^0.4.0": + version: 0.4.0 + resolution: "@changesets/get-version-range-type@npm:0.4.0" + checksum: 10/9868e99b31af652d3fa08fc33d55b9636f2feed1f4efdb318a6dbb4bb061281868de089b93041ce7f2775ab9cf454b92b1199767d0f4f228d8bbc483e61d2fd8 + languageName: node + linkType: hard + +"@changesets/git@npm:^3.0.2": + version: 3.0.2 + resolution: "@changesets/git@npm:3.0.2" + dependencies: + "@changesets/errors": "npm:^0.2.0" + "@manypkg/get-packages": "npm:^1.1.3" + is-subdir: "npm:^1.1.1" + micromatch: "npm:^4.0.8" + spawndamnit: "npm:^3.0.1" + checksum: 10/de63573fecbd2ddcb8b5a7bfe18344a849810035e6fc55aa05e022d42e8cbefdfe23eebcfd34d31e84d78a616aa80ffb239b9e24abc4fc3ebaba10e619f72a24 + languageName: node + linkType: hard + +"@changesets/logger@npm:^0.1.1": + version: 0.1.1 + resolution: "@changesets/logger@npm:0.1.1" + dependencies: + picocolors: "npm:^1.1.0" + checksum: 10/bbfc050ddd0afdaa95bb790e81894b7548a2def059deeaed1685e22c10ede245ec2264df42bb2200cc0c8bd040e427bcd68a7afcca2633dc263a28e923d7c175 + languageName: node + linkType: hard + +"@changesets/parse@npm:^0.4.0": + version: 0.4.0 + resolution: "@changesets/parse@npm:0.4.0" + dependencies: + "@changesets/types": "npm:^6.0.0" + js-yaml: "npm:^3.13.1" + checksum: 10/0a824582306b198cd775048876e62bd39193b921515608504777407d78f1dcc700ec15e1a6bccd8a3514c5acc6c3fb060238fbfeae94e698aa17dad1121c2d43 + languageName: node + linkType: hard + +"@changesets/pre@npm:^2.0.1": + version: 2.0.1 + resolution: "@changesets/pre@npm:2.0.1" + dependencies: + "@changesets/errors": "npm:^0.2.0" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + fs-extra: "npm:^7.0.1" + checksum: 10/e26ca45a1accc4c79890220acf4c85ff716bc09a8e534c91f08bf7d5272408bd76f54ddf6a01765a1aab2517b7447285ae0a9787a6f2135011ad37bcf3f70e48 + languageName: node + linkType: hard + +"@changesets/read@npm:^0.6.2": + version: 0.6.2 + resolution: "@changesets/read@npm:0.6.2" + dependencies: + "@changesets/git": "npm:^3.0.2" + "@changesets/logger": "npm:^0.1.1" + "@changesets/parse": "npm:^0.4.0" + "@changesets/types": "npm:^6.0.0" + fs-extra: "npm:^7.0.1" + p-filter: "npm:^2.1.0" + picocolors: "npm:^1.1.0" + checksum: 10/a9e322c9afb4039c769f71370da1879bb4d457417611d64b1782242b9d2fe9d330816c44f93aebee158fb3e3aee402da50b4e98ac7a779a19d8081478975ec02 + languageName: node + linkType: hard + +"@changesets/should-skip-package@npm:^0.1.1": + version: 0.1.1 + resolution: "@changesets/should-skip-package@npm:0.1.1" + dependencies: + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + checksum: 10/d187ef22495deb63e678d0ff65e8627701e2b52c25bd59dde10ce8646be8d605c0ed0a6af020dd825b137c2fc748fdc6cef52e7774bad4c7a4f404bf182a85cf + languageName: node + linkType: hard + +"@changesets/types@npm:^4.0.1": + version: 4.1.0 + resolution: "@changesets/types@npm:4.1.0" + checksum: 10/4d7c65a447400ac474b2dc2d79bc1a5341c305fbce4a648ef59d9939bc1bbbbd6852684c417a9a4ef0226468b9cb522b9ac2b5393f21fa5f20f1b12bee94eab5 + languageName: node + linkType: hard + +"@changesets/types@npm:^6.0.0": + version: 6.0.0 + resolution: "@changesets/types@npm:6.0.0" + checksum: 10/214c58ff3e3da019c578b94815ec6748729a38b665d950acddf53f3a23073ac7a57dce45812c4bec0cbcd6902c84a482c804457d4c903602005b2399de8a4021 + languageName: node + linkType: hard + +"@changesets/write@npm:^0.3.2": + version: 0.3.2 + resolution: "@changesets/write@npm:0.3.2" + dependencies: + "@changesets/types": "npm:^6.0.0" + fs-extra: "npm:^7.0.1" + human-id: "npm:^1.0.2" + prettier: "npm:^2.7.1" + checksum: 10/c16b0a731fa43ae0028fd1f956c7b080030c42ff763f8dac74da8b178a4ea65632831c30550b784286277bdc75a3c44dda46aad8db97f43bb1eb4d61922152aa + languageName: node + linkType: hard + "@codemirror/autocomplete@npm:^6.12.0": version: 6.12.0 resolution: "@codemirror/autocomplete@npm:6.12.0" @@ -3182,6 +3502,43 @@ __metadata: languageName: node linkType: hard +"@eth-optimism/contracts@npm:0.6.0": + version: 0.6.0 + resolution: "@eth-optimism/contracts@npm:0.6.0" + dependencies: + "@eth-optimism/core-utils": "npm:0.12.0" + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/abstract-signer": "npm:^5.7.0" + peerDependencies: + ethers: ^5 + checksum: 10/dd1fa303ca39125d45fa71a2be0fe773971a986d0694ba98075b9b93ee3c0c71764fd061f1094f82c36d5aa167f5340ec92ef1ec45d901cb69ace086327c0cf2 + languageName: node + linkType: hard + +"@eth-optimism/core-utils@npm:0.12.0": + version: 0.12.0 + resolution: "@eth-optimism/core-utils@npm:0.12.0" + dependencies: + "@ethersproject/abi": "npm:^5.7.0" + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/contracts": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/providers": "npm:^5.7.0" + "@ethersproject/rlp": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/web": "npm:^5.7.0" + bufio: "npm:^1.0.7" + chai: "npm:^4.3.4" + checksum: 10/a7ea17a8b529b2c86b00ef19fa562c2b792d7e8a4071defea4d8a8b82a101105a3ab6dc86361118e17bf9b4784b4eca9c1e937c8b1e7294a1a850f97b5a73a10 + languageName: node + linkType: hard + "@ethereumjs/common@npm:^3.2.0": version: 3.2.0 resolution: "@ethereumjs/common@npm:3.2.0" @@ -3468,7 +3825,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.7.2": +"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.7.0, @ethersproject/providers@npm:^5.7.2": version: 5.7.2 resolution: "@ethersproject/providers@npm:5.7.2" dependencies: @@ -5036,6 +5393,7 @@ __metadata: version: 0.0.0-use.local resolution: "@kleros/kleros-v2-contracts@workspace:contracts" dependencies: + "@chainlink/contracts": "npm:^1.3.0" "@defi-wonderland/natspec-smells": "npm:^1.1.5" "@kleros/kleros-v2-eslint-config": "workspace:^" "@kleros/kleros-v2-prettier-config": "workspace:^" @@ -5634,6 +5992,32 @@ __metadata: languageName: node linkType: hard +"@manypkg/find-root@npm:^1.1.0": + version: 1.1.0 + resolution: "@manypkg/find-root@npm:1.1.0" + dependencies: + "@babel/runtime": "npm:^7.5.5" + "@types/node": "npm:^12.7.1" + find-up: "npm:^4.1.0" + fs-extra: "npm:^8.1.0" + checksum: 10/31e7dde82612a0e37ebb07876d76b1bf2aedc5b285b5e50d94cdf63edbf1fa3970349b84a5837a3c687e5b643e9a4f4588ae1f4b4ae9d412516d57bf977a08db + languageName: node + linkType: hard + +"@manypkg/get-packages@npm:^1.1.3": + version: 1.1.3 + resolution: "@manypkg/get-packages@npm:1.1.3" + dependencies: + "@babel/runtime": "npm:^7.5.5" + "@changesets/types": "npm:^4.0.1" + "@manypkg/find-root": "npm:^1.1.0" + fs-extra: "npm:^8.1.0" + globby: "npm:^11.0.0" + read-yaml-file: "npm:^1.1.0" + checksum: 10/4912e002199ff3974ec48586376a04c5f1815a4faa5f4d36b0698838eec143c9d4e3d42c41e0de009f48a1e2251802ed63c1311ab44de225b50102f85919a248 + languageName: node + linkType: hard + "@mapbox/node-pre-gyp@npm:^1.0.0": version: 1.0.11 resolution: "@mapbox/node-pre-gyp@npm:1.0.11" @@ -6667,6 +7051,15 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/slang@npm:^0.18.3": + version: 0.18.3 + resolution: "@nomicfoundation/slang@npm:0.18.3" + dependencies: + "@bytecodealliance/preview2-shim": "npm:0.17.0" + checksum: 10/1dcf687e4719844bffc688d13d15c0db3218ab05983d6b53777a3172c7df157c105171e802fe7812d9fd2bdb4dcd8d7287367c851eed4dfd76621e799c14574f + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1" @@ -7016,6 +7409,72 @@ __metadata: languageName: node linkType: hard +"@offchainlabs/upgrade-executor@npm:1.1.0-beta.0": + version: 1.1.0-beta.0 + resolution: "@offchainlabs/upgrade-executor@npm:1.1.0-beta.0" + dependencies: + "@openzeppelin/contracts": "npm:4.7.3" + "@openzeppelin/contracts-upgradeable": "npm:4.7.3" + checksum: 10/a8cd0cc24103cc42021c452220005efde535ba3596ec2ba5eb6dc299d1f3291c38a3d859621d7983bd7c43c80606d6e7d906e1081a1e499455ddea7ba64ab355 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:4.5.2": + version: 4.5.2 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.5.2" + checksum: 10/5e246da7a44bb982a312ebf79978735712140692d46273566e490159b98b9041ca72cc08c3d05172137a389be4caad5afc001480bc5557f3d47162f4626e3723 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:4.7.3": + version: 4.7.3 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.7.3" + checksum: 10/7c72ffeca867478b5aa8e8c7adb3d1ce114cfdc797ed4f3cd074788cf4da25d620ffffd624ac7e9d1223eecffeea9f7b79200ff70dc464cc828c470ccd12ddf1 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:4.8.3": + version: 4.8.3 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.8.3" + checksum: 10/1ff70629f509221ef948da6de582fd19a6cf7deea884f0c2de1347ca5eb1f3910099f92fcaf1a70fcae982d8f95b58f48548d833e6ad708e5d7afbae1556fae8 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:4.9.3": + version: 4.9.3 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.3" + checksum: 10/d8fd6fd9d2271fbdd3958c20769b72a241687883ecd3bea05a3969568cdcabdee9d53c21ac776a651c397507d9c22d8db0a4fb970d27bdab918979fae7285a2f + languageName: node + linkType: hard + +"@openzeppelin/contracts@npm:4.5.0": + version: 4.5.0 + resolution: "@openzeppelin/contracts@npm:4.5.0" + checksum: 10/8bfa1733732420331728cedd7f1f5f4e4ae0700b32c9e5def19b2d42dbb0b246709e8e22abd457e8269d743012ff2aed4e3f100a942f45d9507cb78d5dbd435b + languageName: node + linkType: hard + +"@openzeppelin/contracts@npm:4.7.3": + version: 4.7.3 + resolution: "@openzeppelin/contracts@npm:4.7.3" + checksum: 10/3d16ed8943938373ecc331c2ab83c3e8d0d89aed0c2a109aaa61ca6524b4c31cb5a81185c6f93ce9ee2dda685a4328fd85bd217929ae598f4be813d5d4cd1b78 + languageName: node + linkType: hard + +"@openzeppelin/contracts@npm:4.8.3": + version: 4.8.3 + resolution: "@openzeppelin/contracts@npm:4.8.3" + checksum: 10/276481d76afdc71690bd4204cdd47e6add30d183e20df57c76e5ffc481c783ca756842f3b0ac7e3e6336217dcde448cef8279fafae1176ac436ad86594c4bdc2 + languageName: node + linkType: hard + +"@openzeppelin/contracts@npm:4.9.3": + version: 4.9.3 + resolution: "@openzeppelin/contracts@npm:4.9.3" + checksum: 10/ce0a16a56a39b62d72370ac702bce1917096492442ff05de88521beda2c3f3935b93ee2b9a184614dd543a6181f2f0be10243f5a629be87aab284ade68c18320 + languageName: node + linkType: hard + "@openzeppelin/contracts@npm:^5.1.0": version: 5.1.0 resolution: "@openzeppelin/contracts@npm:5.1.0" @@ -7023,6 +7482,26 @@ __metadata: languageName: node linkType: hard +"@openzeppelin/upgrades-core@npm:^1.24.1": + version: 1.41.0 + resolution: "@openzeppelin/upgrades-core@npm:1.41.0" + dependencies: + "@nomicfoundation/slang": "npm:^0.18.3" + cbor: "npm:^9.0.0" + chalk: "npm:^4.1.0" + compare-versions: "npm:^6.0.0" + debug: "npm:^4.1.1" + ethereumjs-util: "npm:^7.0.3" + minimatch: "npm:^9.0.5" + minimist: "npm:^1.2.7" + proper-lockfile: "npm:^4.1.1" + solidity-ast: "npm:^0.4.51" + bin: + openzeppelin-upgrades-core: dist/cli/cli.js + checksum: 10/fb8b6c11326f71809dd07b2b451daf037d99cc8c6748ca82b47fe4573314ca4c037f872945c7f02b072cb9af4309e56323ba3a1b754ecfaaaa480ee4e416280c + languageName: node + linkType: hard + "@parcel/watcher-android-arm64@npm:2.3.0": version: 2.3.0 resolution: "@parcel/watcher-android-arm64@npm:2.3.0" @@ -7762,6 +8241,13 @@ __metadata: languageName: node linkType: hard +"@scroll-tech/contracts@npm:0.1.0": + version: 0.1.0 + resolution: "@scroll-tech/contracts@npm:0.1.0" + checksum: 10/7b32c4fbd7bafccb4c44f435764e9869486f0094759db24fca5021a3001ea61983a1902eff772c3d003a16470bde28859c975b3a6736264d651695dfbfc3665b + languageName: node + linkType: hard + "@scure/base@npm:^1.1.3, @scure/base@npm:~1.1.0, @scure/base@npm:~1.1.2, @scure/base@npm:~1.1.6, @scure/base@npm:~1.1.7, @scure/base@npm:~1.1.8": version: 1.1.9 resolution: "@scure/base@npm:1.1.9" @@ -9489,7 +9975,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^12.12.54": +"@types/node@npm:^12.12.54, @types/node@npm:^12.7.1": version: 12.20.55 resolution: "@types/node@npm:12.20.55" checksum: 10/1f916a06fff02faadb09a16ed6e31820ce170798b202ef0b14fc244bfbd721938c54a3a99836e185e4414ca461fe96c5bb5c67c3d248f153555b7e6347f061dd @@ -11563,6 +12049,13 @@ __metadata: languageName: node linkType: hard +"@yarnpkg/lockfile@npm:^1.1.0": + version: 1.1.0 + resolution: "@yarnpkg/lockfile@npm:1.1.0" + checksum: 10/cd19e1114aaf10a05126aeea8833ef4ca8af8a46e88e12884f8359d19333fd19711036dbc2698dbe937f81f037070cf9a8da45c2e8c6ca19cafd7d15659094ed + languageName: node + linkType: hard + "@yornaath/batshit-devtools@npm:^1.6.0": version: 1.6.0 resolution: "@yornaath/batshit-devtools@npm:1.6.0" @@ -11579,6 +12072,13 @@ __metadata: languageName: node linkType: hard +"@zksync/contracts@git+https://github.com/matter-labs/era-contracts.git#446d391d34bdb48255d5f8fef8a8248925fc98b9": + version: 0.1.0 + resolution: "@zksync/contracts@https://github.com/matter-labs/era-contracts.git#commit=446d391d34bdb48255d5f8fef8a8248925fc98b9" + checksum: 10/982b27c109e55a332f6690e164230a033f3c8292dc816b46798704410796caee5b7b3336d9fd238b5b2aedc7a8ffb54ee294e948d11cfb22e925a4c17392e5ab + languageName: node + linkType: hard + "JSONStream@npm:1.3.2": version: 1.3.2 resolution: "JSONStream@npm:1.3.2" @@ -13007,6 +13507,15 @@ __metadata: languageName: node linkType: hard +"better-path-resolve@npm:1.0.0": + version: 1.0.0 + resolution: "better-path-resolve@npm:1.0.0" + dependencies: + is-windows: "npm:^1.0.0" + checksum: 10/5392dbe04e7fe68b944eb37961d9dfa147aaac3ee9ee3f6e13d42e2c9fbe949e68d16e896c14ee9016fa5f8e6e53ec7fd8b5f01b50a32067a7d94ac9cfb9a050 + languageName: node + linkType: hard + "bfj@npm:^7.0.2": version: 7.0.2 resolution: "bfj@npm:7.0.2" @@ -13306,6 +13815,15 @@ __metadata: languageName: node linkType: hard +"braces@npm:^3.0.3": + version: 3.0.3 + resolution: "braces@npm:3.0.3" + dependencies: + fill-range: "npm:^7.1.1" + checksum: 10/fad11a0d4697a27162840b02b1fad249c1683cbc510cd5bf1a471f2f8085c046d41094308c577a50a03a579dd99d5a6b3724c4b5e8b14df2c4443844cfcda2c6 + languageName: node + linkType: hard + "brorand@npm:^1.0.1, brorand@npm:^1.1.0": version: 1.1.0 resolution: "brorand@npm:1.1.0" @@ -13570,6 +14088,13 @@ __metadata: languageName: node linkType: hard +"bufio@npm:^1.0.7": + version: 1.2.2 + resolution: "bufio@npm:1.2.2" + checksum: 10/dcf0ab4f753a0af1c4215b41bd12596038d3111299673dd14aeee55206a6aa53b44292dc965cef0a41b008ddaeb38ccc9165f2d1cad0da5c8ba3754ef4b45aa1 + languageName: node + linkType: hard + "buildcheck@npm:~0.0.6": version: 0.0.6 resolution: "buildcheck@npm:0.0.6" @@ -13843,6 +14368,15 @@ __metadata: languageName: node linkType: hard +"cbor@npm:^9.0.0": + version: 9.0.2 + resolution: "cbor@npm:9.0.2" + dependencies: + nofilter: "npm:^3.1.0" + checksum: 10/a64f7d4dafed933adeafe7745e2ce9f39a2e669eba73db96de6bd1b39c2dbde4bdd51d0240beed179cc429a7dc8653c8d7c991c5addb9f4e0cee8cd167d87116 + languageName: node + linkType: hard + "cborg@npm:^1.5.4, cborg@npm:^1.6.0, cborg@npm:^1.9.0": version: 1.10.2 resolution: "cborg@npm:1.10.2" @@ -13896,7 +14430,7 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.10, chai@npm:^4.5.0": +"chai@npm:^4.3.10, chai@npm:^4.3.4, chai@npm:^4.5.0": version: 4.5.0 resolution: "chai@npm:4.5.0" dependencies: @@ -14168,6 +14702,13 @@ __metadata: languageName: node linkType: hard +"ci-info@npm:^3.7.0": + version: 3.9.0 + resolution: "ci-info@npm:3.9.0" + checksum: 10/75bc67902b4d1c7b435497adeb91598f6d52a3389398e44294f6601b20cfef32cf2176f7be0eb961d9e085bb333a8a5cae121cb22f81cf238ae7f58eb80e9397 + languageName: node + linkType: hard + "cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": version: 1.0.4 resolution: "cipher-base@npm:1.0.4" @@ -14680,7 +15221,7 @@ __metadata: languageName: node linkType: hard -"compare-versions@npm:^6.1.1": +"compare-versions@npm:^6.0.0, compare-versions@npm:^6.1.1": version: 6.1.1 resolution: "compare-versions@npm:6.1.1" checksum: 10/9325c0fadfba81afa0ec17e6fc2ef823ba785c693089698b8d9374e5460509f1916a88591644d4cb4045c9a58e47fafbcc0724fe8bf446d2a875a3d6eeddf165 @@ -15801,6 +16342,13 @@ __metadata: languageName: node linkType: hard +"dataloader@npm:^1.4.0": + version: 1.4.0 + resolution: "dataloader@npm:1.4.0" + checksum: 10/8dc2181f7fc243f657aa97b5aa51b9e0da88dee9a59a689bab50d4bac826c27ae0457db8d9a5d59559d636f6b997f419303ccfde595cc26191f37ab9c792fe01 + languageName: node + linkType: hard + "dataloader@npm:^2.2.2": version: 2.2.2 resolution: "dataloader@npm:2.2.2" @@ -16638,7 +17186,7 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^8.2.0": +"dotenv@npm:^8.1.0, dotenv@npm:^8.2.0": version: 8.6.0 resolution: "dotenv@npm:8.6.0" checksum: 10/31d7b5c010cebb80046ba6853d703f9573369b00b15129536494f04b0af4ea0060ce8646e3af58b455af2f6f1237879dd261a5831656410ec92561ae1ea44508 @@ -18109,7 +18657,7 @@ __metadata: languageName: node linkType: hard -"ethereumjs-util@npm:^7.1.0, ethereumjs-util@npm:^7.1.5": +"ethereumjs-util@npm:^7.0.3, ethereumjs-util@npm:^7.1.0, ethereumjs-util@npm:^7.1.5": version: 7.1.5 resolution: "ethereumjs-util@npm:7.1.5" dependencies: @@ -18394,6 +18942,13 @@ __metadata: languageName: node linkType: hard +"extendable-error@npm:^0.1.5": + version: 0.1.7 + resolution: "extendable-error@npm:0.1.7" + checksum: 10/80478be7429a1675d2085f701239796bab3230ed6f2fb1b138fbabec24bea6516b7c5ceb6e9c209efcc9c089948d93715703845653535f8e8a49655066a9255e + languageName: node + linkType: hard + "extension-port-stream@npm:^3.0.0": version: 3.0.0 resolution: "extension-port-stream@npm:3.0.0" @@ -18404,7 +18959,7 @@ __metadata: languageName: node linkType: hard -"external-editor@npm:^3.0.3": +"external-editor@npm:^3.0.3, external-editor@npm:^3.1.0": version: 3.1.0 resolution: "external-editor@npm:3.1.0" dependencies: @@ -18754,6 +19309,15 @@ __metadata: languageName: node linkType: hard +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" + dependencies: + to-regex-range: "npm:^5.0.1" + checksum: 10/a7095cb39e5bc32fada2aa7c7249d3f6b01bd1ce461a61b0adabacccabd9198500c6fb1f68a7c851a657e273fce2233ba869638897f3d7ed2e87a2d89b4436ea + languageName: node + linkType: hard + "filter-obj@npm:^1.1.0": version: 1.1.0 resolution: "filter-obj@npm:1.1.0" @@ -18851,6 +19415,15 @@ __metadata: languageName: node linkType: hard +"find-yarn-workspace-root@npm:^2.0.0": + version: 2.0.0 + resolution: "find-yarn-workspace-root@npm:2.0.0" + dependencies: + micromatch: "npm:^4.0.2" + checksum: 10/7fa7942849eef4d5385ee96a0a9a5a9afe885836fd72ed6a4280312a38690afea275e7d09b343fe97daf0412d833f8ac4b78c17fc756386d9ebebf0759d707a7 + languageName: node + linkType: hard + "findup-sync@npm:^5.0.0": version: 5.0.0 resolution: "findup-sync@npm:5.0.0" @@ -19683,7 +20256,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:^11.0.3, globby@npm:^11.0.4, globby@npm:^11.1.0": +"globby@npm:^11.0.0, globby@npm:^11.0.3, globby@npm:^11.0.4, globby@npm:^11.1.0": version: 11.1.0 resolution: "globby@npm:11.1.0" dependencies: @@ -19842,7 +20415,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10/bf152d0ed1dc159239db1ba1f74fdbc40cb02f626770dcd5815c427ce0688c2635a06ed69af364396da4636d0408fcf7d4afdf7881724c3307e46aff30ca49e2 @@ -20801,6 +21374,13 @@ __metadata: languageName: node linkType: hard +"human-id@npm:^1.0.2": + version: 1.0.2 + resolution: "human-id@npm:1.0.2" + checksum: 10/16b116ef68c3fc3f65c90b32a338abd0f9ee656a6257baa92c4d7e1154c66469bb6bd4ee840018c35e972aa817f5ae3f0cbabffb78f2ac90aaf02d88a299a371 + languageName: node + linkType: hard + "human-signals@npm:^2.1.0": version: 2.1.0 resolution: "human-signals@npm:2.1.0" @@ -21618,6 +22198,17 @@ __metadata: languageName: node linkType: hard +"is-ci@npm:^2.0.0": + version: 2.0.0 + resolution: "is-ci@npm:2.0.0" + dependencies: + ci-info: "npm:^2.0.0" + bin: + is-ci: bin.js + checksum: 10/77b869057510f3efa439bbb36e9be429d53b3f51abd4776eeea79ab3b221337fe1753d1e50058a9e2c650d38246108beffb15ccfd443929d77748d8c0cc90144 + languageName: node + linkType: hard + "is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1, is-core-module@npm:^2.5.0": version: 2.15.1 resolution: "is-core-module@npm:2.15.1" @@ -22012,6 +22603,15 @@ __metadata: languageName: node linkType: hard +"is-subdir@npm:^1.1.1": + version: 1.2.0 + resolution: "is-subdir@npm:1.2.0" + dependencies: + better-path-resolve: "npm:1.0.0" + checksum: 10/31029a383972bff4cc4f1bd1463fd04dde017e0a04ae3a6f6e08124a90c6c4656312d593101b0f38805fa3f3c8f6bc4583524bbf72c50784fa5ca0d3e5a76279 + languageName: node + linkType: hard + "is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": version: 1.0.4 resolution: "is-symbol@npm:1.0.4" @@ -22104,14 +22704,14 @@ __metadata: languageName: node linkType: hard -"is-windows@npm:^1.0.1": +"is-windows@npm:^1.0.0, is-windows@npm:^1.0.1": version: 1.0.2 resolution: "is-windows@npm:1.0.2" checksum: 10/438b7e52656fe3b9b293b180defb4e448088e7023a523ec21a91a80b9ff8cdb3377ddb5b6e60f7c7de4fa8b63ab56e121b6705fe081b3cf1b828b0a380009ad7 languageName: node linkType: hard -"is-wsl@npm:^2.2.0": +"is-wsl@npm:^2.1.1, is-wsl@npm:^2.2.0": version: 2.2.0 resolution: "is-wsl@npm:2.2.0" dependencies: @@ -23217,7 +23817,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:3.14.1, js-yaml@npm:3.x, js-yaml@npm:^3.13.1, js-yaml@npm:^3.14.1": +"js-yaml@npm:3.14.1, js-yaml@npm:3.x, js-yaml@npm:^3.13.1, js-yaml@npm:^3.14.1, js-yaml@npm:^3.6.1": version: 3.14.1 resolution: "js-yaml@npm:3.14.1" dependencies: @@ -23614,6 +24214,15 @@ __metadata: languageName: node linkType: hard +"klaw-sync@npm:^6.0.0": + version: 6.0.0 + resolution: "klaw-sync@npm:6.0.0" + dependencies: + graceful-fs: "npm:^4.1.11" + checksum: 10/0da397f8961313c3ef8f79fb63af9002cde5a8fb2aeb1a37351feff0dd6006129c790400c3f5c3b4e757bedcabb13d21ec0a5eaef5a593d59515d4f2c291e475 + languageName: node + linkType: hard + "kleros-v2@workspace:.": version: 0.0.0-use.local resolution: "kleros-v2@workspace:." @@ -25491,6 +26100,16 @@ __metadata: languageName: node linkType: hard +"micromatch@npm:^4.0.8": + version: 4.0.8 + resolution: "micromatch@npm:4.0.8" + dependencies: + braces: "npm:^3.0.3" + picomatch: "npm:^2.3.1" + checksum: 10/6bf2a01672e7965eb9941d1f02044fad2bd12486b5553dc1116ff24c09a8723157601dc992e74c911d896175918448762df3b3fd0a6b61037dd1a9766ddfbf58 + languageName: node + linkType: hard + "miller-rabin@npm:^4.0.0": version: 4.0.1 resolution: "miller-rabin@npm:4.0.1" @@ -25683,7 +26302,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6": +"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.7": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 10/908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f @@ -26416,6 +27035,13 @@ __metadata: languageName: node linkType: hard +"nofilter@npm:^3.1.0": + version: 3.1.0 + resolution: "nofilter@npm:3.1.0" + checksum: 10/f63d87231dfda4b783db17d75b15aac948f78e65f4f1043096ef441147f6667ff74cd4b3f57ada5dbe240be282d3e9838558ac863a66cb04ef25fff7b2b4be4e + languageName: node + linkType: hard + "nopt@npm:3.x": version: 3.0.6 resolution: "nopt@npm:3.0.6" @@ -26825,6 +27451,16 @@ __metadata: languageName: node linkType: hard +"open@npm:^7.4.2": + version: 7.4.2 + resolution: "open@npm:7.4.2" + dependencies: + is-docker: "npm:^2.0.0" + is-wsl: "npm:^2.1.1" + checksum: 10/4fc02ed3368dcd5d7247ad3566433ea2695b0713b041ebc0eeb2f0f9e5d4e29fc2068f5cdd500976b3464e77fe8b61662b1b059c73233ccc601fe8b16d6c1cd6 + languageName: node + linkType: hard + "open@npm:^8.0.9, open@npm:^8.4.0": version: 8.4.2 resolution: "open@npm:8.4.2" @@ -26934,6 +27570,13 @@ __metadata: languageName: node linkType: hard +"outdent@npm:^0.5.0": + version: 0.5.0 + resolution: "outdent@npm:0.5.0" + checksum: 10/7d94a7d93883afa32c99d84f33248b221f4eeeedbb571921fe0e5cf0bee32e64746c587e9606d98ec22762870c782d21dd4bc3a0edf442d347cb54aa107b198d + languageName: node + linkType: hard + "overlayscrollbars-react@npm:^0.5.6": version: 0.5.6 resolution: "overlayscrollbars-react@npm:0.5.6" @@ -27018,6 +27661,15 @@ __metadata: languageName: node linkType: hard +"p-filter@npm:^2.1.0": + version: 2.1.0 + resolution: "p-filter@npm:2.1.0" + dependencies: + p-map: "npm:^2.0.0" + checksum: 10/76e552ca624ce2233448d68b19eec9de42b695208121998f7e011edce71d1079a83096ee6a2078fb2a59cfa8a5c999f046edf00ebf16a8e780022010b4693234 + languageName: node + linkType: hard + "p-finally@npm:^1.0.0": version: 1.0.0 resolution: "p-finally@npm:1.0.0" @@ -27200,6 +27852,13 @@ __metadata: languageName: node linkType: hard +"package-manager-detector@npm:^0.2.0": + version: 0.2.5 + resolution: "package-manager-detector@npm:0.2.5" + checksum: 10/97127289fffc238f6af5af3339c309a3b25f5b360b8d503f8d27cc3afa259732a08e7df9331f703b1db0c585504f70ade9b068ddf40949f6dd8a5ebbb9ab8d67 + languageName: node + linkType: hard + "pako@npm:~1.0.5": version: 1.0.11 resolution: "pako@npm:1.0.11" @@ -27370,6 +28029,30 @@ __metadata: languageName: node linkType: hard +"patch-package@npm:^6.4.7": + version: 6.5.1 + resolution: "patch-package@npm:6.5.1" + dependencies: + "@yarnpkg/lockfile": "npm:^1.1.0" + chalk: "npm:^4.1.2" + cross-spawn: "npm:^6.0.5" + find-yarn-workspace-root: "npm:^2.0.0" + fs-extra: "npm:^9.0.0" + is-ci: "npm:^2.0.0" + klaw-sync: "npm:^6.0.0" + minimist: "npm:^1.2.6" + open: "npm:^7.4.2" + rimraf: "npm:^2.6.3" + semver: "npm:^5.6.0" + slash: "npm:^2.0.0" + tmp: "npm:^0.0.33" + yaml: "npm:^1.10.2" + bin: + patch-package: index.js + checksum: 10/e15b3848f008da2cc659abd6d84dfeab6ed25a999ba25692071c13409f198dad28b6e451ecfebc2139a0847ad8e608575d6724bcc887c56169df8a733b849e79 + languageName: node + linkType: hard + "path-browserify@npm:^1.0.1": version: 1.0.1 resolution: "path-browserify@npm:1.0.1" @@ -28728,7 +29411,7 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^1.18.2 || ^2.0.0, prettier@npm:^2.1.2, prettier@npm:^2.3.1, prettier@npm:^2.8.3": +"prettier@npm:^1.18.2 || ^2.0.0, prettier@npm:^2.1.2, prettier@npm:^2.3.1, prettier@npm:^2.7.1, prettier@npm:^2.8.3": version: 2.8.8 resolution: "prettier@npm:2.8.8" bin: @@ -28881,6 +29564,17 @@ __metadata: languageName: node linkType: hard +"proper-lockfile@npm:^4.1.1": + version: 4.1.2 + resolution: "proper-lockfile@npm:4.1.2" + dependencies: + graceful-fs: "npm:^4.2.4" + retry: "npm:^0.12.0" + signal-exit: "npm:^3.0.2" + checksum: 10/000a4875f543f591872b36ca94531af8a6463ddb0174f41c0b004d19e231d7445268b422ff1ea595e43d238655c702250cd3d27f408e7b9d97b56f1533ba26bf + languageName: node + linkType: hard + "property-information@npm:^6.0.0": version: 6.2.0 resolution: "property-information@npm:6.2.0" @@ -29878,6 +30572,18 @@ __metadata: languageName: node linkType: hard +"read-yaml-file@npm:^1.1.0": + version: 1.1.0 + resolution: "read-yaml-file@npm:1.1.0" + dependencies: + graceful-fs: "npm:^4.1.5" + js-yaml: "npm:^3.6.1" + pify: "npm:^4.0.1" + strip-bom: "npm:^3.0.0" + checksum: 10/41ee5f075507ef0403328dd54e225a61c3149f915675ce7fd0fd791ddcce2e6c30a9fe0f76ffa7a465c1c157b9b4ad8ded1dcf47dc3b396103eeb013490bbc2e + languageName: node + linkType: hard + "readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" @@ -31131,6 +31837,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^5.6.0": + version: 5.7.2 + resolution: "semver@npm:5.7.2" + bin: + semver: bin/semver + checksum: 10/fca14418a174d4b4ef1fecb32c5941e3412d52a4d3d85165924ce3a47fbc7073372c26faf7484ceb4bbc2bde25880c6b97e492473dc7e9708fdfb1c6a02d546e + languageName: node + linkType: hard + "semver@npm:^6.0.0, semver@npm:^6.1.0, semver@npm:^6.1.2, semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -31140,7 +31855,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.0, semver@npm:^7.5.2, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.2, semver@npm:^7.6.3": +"semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.0, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.2, semver@npm:^7.6.3": version: 7.6.3 resolution: "semver@npm:7.6.3" bin: @@ -31480,6 +32195,13 @@ __metadata: languageName: node linkType: hard +"slash@npm:^2.0.0": + version: 2.0.0 + resolution: "slash@npm:2.0.0" + checksum: 10/512d4350735375bd11647233cb0e2f93beca6f53441015eea241fe784d8068281c3987fbaa93e7ef1c38df68d9c60013045c92837423c69115297d6169aa85e6 + languageName: node + linkType: hard + "slash@npm:^3.0.0": version: 3.0.0 resolution: "slash@npm:3.0.0" @@ -31712,6 +32434,13 @@ __metadata: languageName: node linkType: hard +"solidity-ast@npm:^0.4.51": + version: 0.4.59 + resolution: "solidity-ast@npm:0.4.59" + checksum: 10/95172fcc3b4ea183c328c36b72b1b861c2e1a2c0f8334f5375f05c1f7a11e13b10f126818dd1a65bb672b4bca87278faaa2bae5c25d2433e162bc86a47d43daa + languageName: node + linkType: hard + "solidity-coverage@npm:^0.8.13": version: 0.8.13 resolution: "solidity-coverage@npm:0.8.13" @@ -31865,6 +32594,16 @@ __metadata: languageName: node linkType: hard +"spawndamnit@npm:^3.0.1": + version: 3.0.1 + resolution: "spawndamnit@npm:3.0.1" + dependencies: + cross-spawn: "npm:^7.0.5" + signal-exit: "npm:^4.0.1" + checksum: 10/47d88a7f1e5691e13e435eddc3d34123c2f7746e2853e91bfac5ea7c6e3bb4b1d1995223b25f7a8745871510d92f63ecd3c9fa02aa2896ac0c79fb618eb08bbe + languageName: node + linkType: hard + "spdx-correct@npm:^3.0.0": version: 3.2.0 resolution: "spdx-correct@npm:3.2.0" @@ -33069,6 +33808,13 @@ __metadata: languageName: node linkType: hard +"term-size@npm:^2.1.0": + version: 2.2.1 + resolution: "term-size@npm:2.2.1" + checksum: 10/f96aca2d4139c91e3359f5949ffb86f0a58f8c254ab7fe4a64b65126974939c782db6aaa91bf51a56d0344e505e22f9a0186f2f689e23ac9382b54606603c537 + languageName: node + linkType: hard + "terminal-link@npm:^2.0.0": version: 2.1.1 resolution: "terminal-link@npm:2.1.1" From 09a13de7ff36472caeb484f597264c237ea0d95e Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Sat, 7 Dec 2024 11:27:44 +0000 Subject: [PATCH 02/12] chore: prettier plugin missing in config --- prettier-config/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/prettier-config/index.js b/prettier-config/index.js index 972950225..9f4d7bbcb 100644 --- a/prettier-config/index.js +++ b/prettier-config/index.js @@ -22,4 +22,5 @@ module.exports = { }, }, ], + plugins: [require("prettier-plugin-solidity")], }; From b0fba7f5f806fb8889023a93641d188dbc7bf0da Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Sat, 7 Dec 2024 13:12:58 +0000 Subject: [PATCH 03/12] feat: chainlink vrf rng deploy script --- contracts/deploy/00-chainlink-rng.ts | 76 + .../arbitrum/ChainlinkVRFCoordinator.json | 18 + .../ChainlinkVRFCoordinator.json | 1753 +++++++++++++++++ .../arbitrumSepoliaDevnet/ChainlinkRNG.json | 736 +++++++ .../ChainlinkVRFCoordinator.json | 1753 +++++++++++++++++ contracts/src/rng/ChainlinkRNG.sol | 2 +- 6 files changed, 4337 insertions(+), 1 deletion(-) create mode 100644 contracts/deploy/00-chainlink-rng.ts create mode 100644 contracts/deployments/arbitrum/ChainlinkVRFCoordinator.json create mode 100644 contracts/deployments/arbitrumSepolia/ChainlinkVRFCoordinator.json create mode 100644 contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json create mode 100644 contracts/deployments/arbitrumSepoliaDevnet/ChainlinkVRFCoordinator.json diff --git a/contracts/deploy/00-chainlink-rng.ts b/contracts/deploy/00-chainlink-rng.ts new file mode 100644 index 000000000..4ff7011e7 --- /dev/null +++ b/contracts/deploy/00-chainlink-rng.ts @@ -0,0 +1,76 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HomeChains, isSkipped } from "./utils"; +import { getContractOrDeploy } from "./utils/getContractOrDeploy"; + +const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { + const { deployments, getNamedAccounts, getChainId } = hre; + const { deploy } = deployments; + + // fallback to hardhat node signers on local network + const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address; + const chainId = Number(await getChainId()) as unknown as HomeChains; // Checked at runtime by skip() + console.log("deploying to %s with deployer %s", HomeChains[chainId], deployer); + + const KEY_HASHES = { + // https://docs.chain.link/vrf/v2-5/supported-networks#arbitrum-mainnet + [HomeChains.ARBITRUM_ONE]: { + 2: "0x9e9e46732b32662b9adc6f3abdf6c5e926a666d174a4d6b8e39c4cca76a38897", + 30: "0x8472ba59cf7134dfe321f4d61a430c4857e8b19cdd5230b09952a92671c24409", + 150: "0xe9f223d7d83ec85c4f78042a4845af3a1c8df7757b4997b815ce4b8d07aca68c", + }, + // https://docs.chain.link/vrf/v2-5/supported-networks#arbitrum-sepolia-testnet + [HomeChains.ARBITRUM_SEPOLIA]: { + 150: "0x1770bdc7eec7771f7ba4ffd640f34260d7f095b79c92d34a5b2551d6f6cfd2be", + }, + [HomeChains.HARDHAT]: { + 0: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + }; + + const SUBSCRIPTION_ID = { + [HomeChains.ARBITRUM_ONE]: "66240499937595191069677958665918759554657443303079118766000192000140992834352", + [HomeChains.ARBITRUM_SEPOLIA]: "38502597312983100069991953687934627561654236680431968938019951490339399569548", + [HomeChains.HARDHAT]: "0x0000000000000000000000000000000000000000000000000000000000000000", + }; + + function getKeyHash({ gasPrice }: { gasPrice: keyof (typeof KEY_HASHES)[HomeChains.ARBITRUM_ONE] }): string { + if (chainId == HomeChains.HARDHAT) return KEY_HASHES[chainId][0]; + if (chainId == HomeChains.ARBITRUM_ONE) return KEY_HASHES[chainId][gasPrice]; + if (chainId == HomeChains.ARBITRUM_SEPOLIA) return KEY_HASHES[chainId][150]; + throw new Error(`Unknown chainId ${chainId}`); + } + + const ChainlinkVRFCoordinator = await getContractOrDeploy(hre, "ChainlinkVRFCoordinator", { + from: deployer, + contract: "ChainlinkVRFCoordinator", + args: [], + log: true, + }); + + const keyHash = getKeyHash({ gasPrice: 150 }); + const subscriptionId = SUBSCRIPTION_ID[chainId]; + const requestConfirmations = 200; // between 1 and 200 L2 blocks + const callbackGasLimit = 100000; + + await deploy("ChainlinkRNG", { + from: deployer, + args: [ + deployer, + deployer, + ChainlinkVRFCoordinator.target, + keyHash, + subscriptionId, + requestConfirmations, + callbackGasLimit, + ], + log: true, + }); +}; + +deployArbitration.tags = ["ChainlinkRNG"]; +deployArbitration.skip = async ({ network }) => { + return isSkipped(network, !HomeChains[network.config.chainId ?? 0]); +}; + +export default deployArbitration; diff --git a/contracts/deployments/arbitrum/ChainlinkVRFCoordinator.json b/contracts/deployments/arbitrum/ChainlinkVRFCoordinator.json new file mode 100644 index 000000000..6dbd1fef2 --- /dev/null +++ b/contracts/deployments/arbitrum/ChainlinkVRFCoordinator.json @@ -0,0 +1,18 @@ +{ + "address": "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] +} diff --git a/contracts/deployments/arbitrumSepolia/ChainlinkVRFCoordinator.json b/contracts/deployments/arbitrumSepolia/ChainlinkVRFCoordinator.json new file mode 100644 index 000000000..0ad1f85b2 --- /dev/null +++ b/contracts/deployments/arbitrumSepolia/ChainlinkVRFCoordinator.json @@ -0,0 +1,1753 @@ +{ + "address": "0x5CE8D5A2BC84beb22a398CCA51996F7930313D61", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "deregisterMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "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": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} diff --git a/contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json b/contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json new file mode 100644 index 000000000..589a64d7f --- /dev/null +++ b/contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json @@ -0,0 +1,736 @@ +{ + "address": "0x1ce7F5771bA530a6b2d7129268E0c04441DF95c9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + }, + { + "internalType": "address", + "name": "_sortitionModule", + "type": "address" + }, + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_subscriptionId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "randomWord", + "type": "uint256" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "callbackGasLimit", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + } + ], + "name": "changeCallbackGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "changeGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + } + ], + "name": "changeKeyHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + } + ], + "name": "changeRequestConfirmations", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_sortitionModule", + "type": "address" + } + ], + "name": "changeSortitionModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_subscriptionId", + "type": "uint256" + } + ], + "name": "changeSubscriptionId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "changeVrfCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "randomNumbers", + "outputs": [ + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "receiveRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "randomNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "requestConfirmations", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "requestRandomness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sortitionModule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subscriptionId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x98e0e5095a628df19a3987f45637207b99ec2e91a7fdfc335244f625ca1faac2", + "receipt": { + "to": null, + "from": "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "contractAddress": "0x1ce7F5771bA530a6b2d7129268E0c04441DF95c9", + "transactionIndex": 1, + "gasUsed": "925617", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x3b1792895296c1c77836af5d139a7883f2abdfc845856c7486214d4fb826f768", + "transactionHash": "0x98e0e5095a628df19a3987f45637207b99ec2e91a7fdfc335244f625ca1faac2", + "logs": [], + "blockNumber": 104436407, + "cumulativeGasUsed": "925617", + "status": 1, + "byzantium": true + }, + "args": [ + "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "0x5CE8D5A2BC84beb22a398CCA51996F7930313D61", + "0x1770bdc7eec7771f7ba4ffd640f34260d7f095b79c92d34a5b2551d6f6cfd2be", + "38502597312983100069991953687934627561654236680431968938019951490339399569548", + 20, + 100000 + ], + "numDeployments": 1, + "solcInputHash": "75a40fe267f89917a94a61837d7b8dfe", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_sortitionModule\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_subscriptionId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"want\",\"type\":\"address\"}],\"name\":\"OnlyCoordinatorCanFulfill\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"OnlyOwnerOrCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vrfCoordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"randomWord\",\"type\":\"uint256\"}],\"name\":\"RequestFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"RequestSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"callbackGasLimit\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"name\":\"changeCallbackGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"}],\"name\":\"changeKeyHash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"}],\"name\":\"changeRequestConfirmations\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sortitionModule\",\"type\":\"address\"}],\"name\":\"changeSortitionModule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_subscriptionId\",\"type\":\"uint256\"}],\"name\":\"changeSubscriptionId\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"changeVrfCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"keyHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"randomNumbers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"receiveRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"randomNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requestConfirmations\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"requestRandomness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_vrfCoordinator\",\"outputs\":[{\"internalType\":\"contract IVRFCoordinatorV2Plus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sortitionModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"subscriptionId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"RequestFulfilled(uint256,uint256)\":{\"params\":{\"randomWord\":\"The random value answering the request.\",\"requestId\":\"The ID of the request\"}},\"RequestSent(uint256)\":{\"details\":\"Emitted when a request is sent to the VRF Coordinator\",\"params\":{\"requestId\":\"The ID of the request\"}}},\"kind\":\"dev\",\"methods\":{\"changeCallbackGasLimit(uint32)\":{\"details\":\"Changes the callback gas limit of the contract.\",\"params\":{\"_callbackGasLimit\":\"The new callback gas limit.\"}},\"changeGovernor(address)\":{\"details\":\"Changes the governor of the contract.\",\"params\":{\"_governor\":\"The new governor.\"}},\"changeKeyHash(bytes32)\":{\"details\":\"Changes the key hash of the contract.\",\"params\":{\"_keyHash\":\"The new key hash.\"}},\"changeRequestConfirmations(uint16)\":{\"details\":\"Changes the request confirmations of the contract.\",\"params\":{\"_requestConfirmations\":\"The new request confirmations.\"}},\"changeSortitionModule(address)\":{\"details\":\"Changes the sortition module of the contract.\",\"params\":{\"_sortitionModule\":\"The new sortition module.\"}},\"changeSubscriptionId(uint256)\":{\"details\":\"Changes the subscription ID of the contract.\",\"params\":{\"_subscriptionId\":\"The new subscription ID.\"}},\"changeVrfCoordinator(address)\":{\"details\":\"Changes the VRF Coordinator of the contract.\",\"params\":{\"_vrfCoordinator\":\"The new VRF Coordinator.\"}},\"constructor\":{\"details\":\"Constructor, initializing the implementation to reduce attack surface.https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number\",\"params\":{\"_callbackGasLimit\":\"The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.\",\"_governor\":\"The Governor of the contract.\",\"_keyHash\":\"The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\",\"_requestConfirmations\":\"How many confirmations the Chainlink node should wait before responding.\",\"_sortitionModule\":\"The address of the SortitionModule contract.\",\"_subscriptionId\":\"The unique identifier of the subscription used for funding requests.\",\"_vrfCoordinator\":\"The address of the VRFCoordinator contract.\"}},\"receiveRandomness(uint256)\":{\"details\":\"Return the random number.\",\"returns\":{\"randomNumber\":\"The random number or 0 if it is not ready or has not been requested.\"}},\"requestRandomness(uint256)\":{\"details\":\"Request a random number. SortitionModule only.\"}},\"title\":\"Random Number Generator that uses Chainlink VRF v2.5 https://blog.chain.link/introducing-vrf-v2-5/\",\"version\":1},\"userdoc\":{\"events\":{\"RequestFulfilled(uint256,uint256)\":{\"notice\":\"Emitted when a request has been fulfilled.\"}},\"kind\":\"user\",\"methods\":{\"acceptOwnership()\":{\"notice\":\"Allows an ownership transfer to be completed by the recipient.\"},\"owner()\":{\"notice\":\"Get the current owner\"},\"setCoordinator(address)\":{\"notice\":\"Sets the VRF Coordinator addressThis method should only be callable by the coordinator or contract owner\"},\"transferOwnership(address)\":{\"notice\":\"Allows an owner to begin transferring ownership to a new address.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/rng/ChainlinkRNG.sol\":\"ChainlinkRNG\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {ConfirmedOwnerWithProposal} from \\\"./ConfirmedOwnerWithProposal.sol\\\";\\n\\n/// @title The ConfirmedOwner contract\\n/// @notice A contract with helpers for basic contract ownership.\\ncontract ConfirmedOwner is ConfirmedOwnerWithProposal {\\n constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}\\n}\\n\",\"keccak256\":\"0xdcb0e9135ddbe71ee27ba99fa06656960c66c964cf2ecb29696da1c1427d9861\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {IOwnable} from \\\"../interfaces/IOwnable.sol\\\";\\n\\n/// @title The ConfirmedOwner contract\\n/// @notice A contract with helpers for basic contract ownership.\\ncontract ConfirmedOwnerWithProposal is IOwnable {\\n address private s_owner;\\n address private s_pendingOwner;\\n\\n event OwnershipTransferRequested(address indexed from, address indexed to);\\n event OwnershipTransferred(address indexed from, address indexed to);\\n\\n constructor(address newOwner, address pendingOwner) {\\n // solhint-disable-next-line gas-custom-errors\\n require(newOwner != address(0), \\\"Cannot set owner to zero\\\");\\n\\n s_owner = newOwner;\\n if (pendingOwner != address(0)) {\\n _transferOwnership(pendingOwner);\\n }\\n }\\n\\n /// @notice Allows an owner to begin transferring ownership to a new address.\\n function transferOwnership(address to) public override onlyOwner {\\n _transferOwnership(to);\\n }\\n\\n /// @notice Allows an ownership transfer to be completed by the recipient.\\n function acceptOwnership() external override {\\n // solhint-disable-next-line gas-custom-errors\\n require(msg.sender == s_pendingOwner, \\\"Must be proposed owner\\\");\\n\\n address oldOwner = s_owner;\\n s_owner = msg.sender;\\n s_pendingOwner = address(0);\\n\\n emit OwnershipTransferred(oldOwner, msg.sender);\\n }\\n\\n /// @notice Get the current owner\\n function owner() public view override returns (address) {\\n return s_owner;\\n }\\n\\n /// @notice validate, transfer ownership, and emit relevant events\\n function _transferOwnership(address to) private {\\n // solhint-disable-next-line gas-custom-errors\\n require(to != msg.sender, \\\"Cannot transfer to self\\\");\\n\\n s_pendingOwner = to;\\n\\n emit OwnershipTransferRequested(s_owner, to);\\n }\\n\\n /// @notice validate access\\n function _validateOwnership() internal view {\\n // solhint-disable-next-line gas-custom-errors\\n require(msg.sender == s_owner, \\\"Only callable by owner\\\");\\n }\\n\\n /// @notice Reverts if called by anyone other than the contract owner.\\n modifier onlyOwner() {\\n _validateOwnership();\\n _;\\n }\\n}\\n\",\"keccak256\":\"0x2422a055657a87e98be61f8f31abb1824ec50fd0f73949f4e3c6ac877efb6da8\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IOwnable {\\n function owner() external returns (address);\\n\\n function transferOwnership(address recipient) external;\\n\\n function acceptOwnership() external;\\n}\\n\",\"keccak256\":\"0x885de72b7b4e4f1bf8ba817a3f2bcc37fd9022d342c4ce76782151c30122d767\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {IVRFCoordinatorV2Plus} from \\\"./interfaces/IVRFCoordinatorV2Plus.sol\\\";\\nimport {IVRFMigratableConsumerV2Plus} from \\\"./interfaces/IVRFMigratableConsumerV2Plus.sol\\\";\\nimport {ConfirmedOwner} from \\\"../../shared/access/ConfirmedOwner.sol\\\";\\n\\n/** ****************************************************************************\\n * @notice Interface for contracts using VRF randomness\\n * *****************************************************************************\\n * @dev PURPOSE\\n *\\n * @dev Reggie the Random Oracle (not his real job) wants to provide randomness\\n * @dev to Vera the verifier in such a way that Vera can be sure he's not\\n * @dev making his output up to suit himself. Reggie provides Vera a public key\\n * @dev to which he knows the secret key. Each time Vera provides a seed to\\n * @dev Reggie, he gives back a value which is computed completely\\n * @dev deterministically from the seed and the secret key.\\n *\\n * @dev Reggie provides a proof by which Vera can verify that the output was\\n * @dev correctly computed once Reggie tells it to her, but without that proof,\\n * @dev the output is indistinguishable to her from a uniform random sample\\n * @dev from the output space.\\n *\\n * @dev The purpose of this contract is to make it easy for unrelated contracts\\n * @dev to talk to Vera the verifier about the work Reggie is doing, to provide\\n * @dev simple access to a verifiable source of randomness. It ensures 2 things:\\n * @dev 1. The fulfillment came from the VRFCoordinatorV2Plus.\\n * @dev 2. The consumer contract implements fulfillRandomWords.\\n * *****************************************************************************\\n * @dev USAGE\\n *\\n * @dev Calling contracts must inherit from VRFConsumerBaseV2Plus, and can\\n * @dev initialize VRFConsumerBaseV2Plus's attributes in their constructor as\\n * @dev shown:\\n *\\n * @dev contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus {\\n * @dev constructor(, address _vrfCoordinator, address _subOwner)\\n * @dev VRFConsumerBaseV2Plus(_vrfCoordinator, _subOwner) public {\\n * @dev \\n * @dev }\\n * @dev }\\n *\\n * @dev The oracle will have given you an ID for the VRF keypair they have\\n * @dev committed to (let's call it keyHash). Create a subscription, fund it\\n * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface\\n * @dev subscription management functions).\\n * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,\\n * @dev callbackGasLimit, numWords, extraArgs),\\n * @dev see (IVRFCoordinatorV2Plus for a description of the arguments).\\n *\\n * @dev Once the VRFCoordinatorV2Plus has received and validated the oracle's response\\n * @dev to your request, it will call your contract's fulfillRandomWords method.\\n *\\n * @dev The randomness argument to fulfillRandomWords is a set of random words\\n * @dev generated from your requestId and the blockHash of the request.\\n *\\n * @dev If your contract could have concurrent requests open, you can use the\\n * @dev requestId returned from requestRandomWords to track which response is associated\\n * @dev with which randomness request.\\n * @dev See \\\"SECURITY CONSIDERATIONS\\\" for principles to keep in mind,\\n * @dev if your contract could have multiple requests in flight simultaneously.\\n *\\n * @dev Colliding `requestId`s are cryptographically impossible as long as seeds\\n * @dev differ.\\n *\\n * *****************************************************************************\\n * @dev SECURITY CONSIDERATIONS\\n *\\n * @dev A method with the ability to call your fulfillRandomness method directly\\n * @dev could spoof a VRF response with any random value, so it's critical that\\n * @dev it cannot be directly called by anything other than this base contract\\n * @dev (specifically, by the VRFConsumerBaseV2Plus.rawFulfillRandomness method).\\n *\\n * @dev For your users to trust that your contract's random behavior is free\\n * @dev from malicious interference, it's best if you can write it so that all\\n * @dev behaviors implied by a VRF response are executed *during* your\\n * @dev fulfillRandomness method. If your contract must store the response (or\\n * @dev anything derived from it) and use it later, you must ensure that any\\n * @dev user-significant behavior which depends on that stored value cannot be\\n * @dev manipulated by a subsequent VRF request.\\n *\\n * @dev Similarly, both miners and the VRF oracle itself have some influence\\n * @dev over the order in which VRF responses appear on the blockchain, so if\\n * @dev your contract could have multiple VRF requests in flight simultaneously,\\n * @dev you must ensure that the order in which the VRF responses arrive cannot\\n * @dev be used to manipulate your contract's user-significant behavior.\\n *\\n * @dev Since the block hash of the block which contains the requestRandomness\\n * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful\\n * @dev miner could, in principle, fork the blockchain to evict the block\\n * @dev containing the request, forcing the request to be included in a\\n * @dev different block with a different hash, and therefore a different input\\n * @dev to the VRF. However, such an attack would incur a substantial economic\\n * @dev cost. This cost scales with the number of blocks the VRF oracle waits\\n * @dev until it calls responds to a request. It is for this reason that\\n * @dev that you can signal to an oracle you'd like them to wait longer before\\n * @dev responding to the request (however this is not enforced in the contract\\n * @dev and so remains effective only in the case of unmodified oracle software).\\n */\\nabstract contract VRFConsumerBaseV2Plus is IVRFMigratableConsumerV2Plus, ConfirmedOwner {\\n error OnlyCoordinatorCanFulfill(address have, address want);\\n error OnlyOwnerOrCoordinator(address have, address owner, address coordinator);\\n error ZeroAddress();\\n\\n // s_vrfCoordinator should be used by consumers to make requests to vrfCoordinator\\n // so that coordinator reference is updated after migration\\n IVRFCoordinatorV2Plus public s_vrfCoordinator;\\n\\n /**\\n * @param _vrfCoordinator address of VRFCoordinator contract\\n */\\n constructor(address _vrfCoordinator) ConfirmedOwner(msg.sender) {\\n if (_vrfCoordinator == address(0)) {\\n revert ZeroAddress();\\n }\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n }\\n\\n /**\\n * @notice fulfillRandomness handles the VRF response. Your contract must\\n * @notice implement it. See \\\"SECURITY CONSIDERATIONS\\\" above for important\\n * @notice principles to keep in mind when implementing your fulfillRandomness\\n * @notice method.\\n *\\n * @dev VRFConsumerBaseV2Plus expects its subcontracts to have a method with this\\n * @dev signature, and will call it once it has verified the proof\\n * @dev associated with the randomness. (It is triggered via a call to\\n * @dev rawFulfillRandomness, below.)\\n *\\n * @param requestId The Id initially returned by requestRandomness\\n * @param randomWords the VRF output expanded to the requested number of words\\n */\\n // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\\n function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal virtual;\\n\\n // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF\\n // proof. rawFulfillRandomness then calls fulfillRandomness, after validating\\n // the origin of the call\\n function rawFulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) external {\\n if (msg.sender != address(s_vrfCoordinator)) {\\n revert OnlyCoordinatorCanFulfill(msg.sender, address(s_vrfCoordinator));\\n }\\n fulfillRandomWords(requestId, randomWords);\\n }\\n\\n /**\\n * @inheritdoc IVRFMigratableConsumerV2Plus\\n */\\n function setCoordinator(address _vrfCoordinator) external override onlyOwnerOrCoordinator {\\n if (_vrfCoordinator == address(0)) {\\n revert ZeroAddress();\\n }\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n\\n emit CoordinatorSet(_vrfCoordinator);\\n }\\n\\n modifier onlyOwnerOrCoordinator() {\\n if (msg.sender != owner() && msg.sender != address(s_vrfCoordinator)) {\\n revert OnlyOwnerOrCoordinator(msg.sender, owner(), address(s_vrfCoordinator));\\n }\\n _;\\n }\\n}\\n\",\"keccak256\":\"0x0c92838396c5abe72754ebeae526a0434dd53fdaf63e6b98111aebd6114cfcc2\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {VRFV2PlusClient} from \\\"../libraries/VRFV2PlusClient.sol\\\";\\nimport {IVRFSubscriptionV2Plus} from \\\"./IVRFSubscriptionV2Plus.sol\\\";\\n\\n// Interface that enables consumers of VRFCoordinatorV2Plus to be future-proof for upgrades\\n// This interface is supported by subsequent versions of VRFCoordinatorV2Plus\\ninterface IVRFCoordinatorV2Plus is IVRFSubscriptionV2Plus {\\n /**\\n * @notice Request a set of random words.\\n * @param req - a struct containing following fields for randomness request:\\n * keyHash - Corresponds to a particular oracle job which uses\\n * that key for generating the VRF proof. Different keyHash's have different gas price\\n * ceilings, so you can select a specific one to bound your maximum per request cost.\\n * subId - The ID of the VRF subscription. Must be funded\\n * with the minimum subscription balance required for the selected keyHash.\\n * requestConfirmations - How many blocks you'd like the\\n * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS\\n * for why you may want to request more. The acceptable range is\\n * [minimumRequestBlockConfirmations, 200].\\n * callbackGasLimit - How much gas you'd like to receive in your\\n * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords\\n * may be slightly less than this amount because of gas used calling the function\\n * (argument decoding etc.), so you may need to request slightly more than you expect\\n * to have inside fulfillRandomWords. The acceptable range is\\n * [0, maxGasLimit]\\n * numWords - The number of uint256 random values you'd like to receive\\n * in your fulfillRandomWords callback. Note these numbers are expanded in a\\n * secure way by the VRFCoordinator from a single random value supplied by the oracle.\\n * extraArgs - abi-encoded extra args\\n * @return requestId - A unique identifier of the request. Can be used to match\\n * a request to a response in fulfillRandomWords.\\n */\\n function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId);\\n}\\n\",\"keccak256\":\"0x7dca2a64690ddd95ee05e422e1f61e7c1d701aaf5be1390ae12e9bd144266c36\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice The IVRFMigratableConsumerV2Plus interface defines the\\n/// @notice method required to be implemented by all V2Plus consumers.\\n/// @dev This interface is designed to be used in VRFConsumerBaseV2Plus.\\ninterface IVRFMigratableConsumerV2Plus {\\n event CoordinatorSet(address vrfCoordinator);\\n\\n /// @notice Sets the VRF Coordinator address\\n /// @notice This method should only be callable by the coordinator or contract owner\\n function setCoordinator(address vrfCoordinator) external;\\n}\\n\",\"keccak256\":\"0x8be8744e3b8380dc85354cf110e8caef8f394266e79120ad675a7da835ed2a85\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice The IVRFSubscriptionV2Plus interface defines the subscription\\n/// @notice related methods implemented by the V2Plus coordinator.\\ninterface IVRFSubscriptionV2Plus {\\n /**\\n * @notice Add a consumer to a VRF subscription.\\n * @param subId - ID of the subscription\\n * @param consumer - New consumer which can use the subscription\\n */\\n function addConsumer(uint256 subId, address consumer) external;\\n\\n /**\\n * @notice Remove a consumer from a VRF subscription.\\n * @param subId - ID of the subscription\\n * @param consumer - Consumer to remove from the subscription\\n */\\n function removeConsumer(uint256 subId, address consumer) external;\\n\\n /**\\n * @notice Cancel a subscription\\n * @param subId - ID of the subscription\\n * @param to - Where to send the remaining LINK to\\n */\\n function cancelSubscription(uint256 subId, address to) external;\\n\\n /**\\n * @notice Accept subscription owner transfer.\\n * @param subId - ID of the subscription\\n * @dev will revert if original owner of subId has\\n * not requested that msg.sender become the new owner.\\n */\\n function acceptSubscriptionOwnerTransfer(uint256 subId) external;\\n\\n /**\\n * @notice Request subscription owner transfer.\\n * @param subId - ID of the subscription\\n * @param newOwner - proposed new owner of the subscription\\n */\\n function requestSubscriptionOwnerTransfer(uint256 subId, address newOwner) external;\\n\\n /**\\n * @notice Create a VRF subscription.\\n * @return subId - A unique subscription id.\\n * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.\\n * @dev Note to fund the subscription with LINK, use transferAndCall. For example\\n * @dev LINKTOKEN.transferAndCall(\\n * @dev address(COORDINATOR),\\n * @dev amount,\\n * @dev abi.encode(subId));\\n * @dev Note to fund the subscription with Native, use fundSubscriptionWithNative. Be sure\\n * @dev to send Native with the call, for example:\\n * @dev COORDINATOR.fundSubscriptionWithNative{value: amount}(subId);\\n */\\n function createSubscription() external returns (uint256 subId);\\n\\n /**\\n * @notice Get a VRF subscription.\\n * @param subId - ID of the subscription\\n * @return balance - LINK balance of the subscription in juels.\\n * @return nativeBalance - native balance of the subscription in wei.\\n * @return reqCount - Requests count of subscription.\\n * @return owner - owner of the subscription.\\n * @return consumers - list of consumer address which are able to use this subscription.\\n */\\n function getSubscription(\\n uint256 subId\\n )\\n external\\n view\\n returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers);\\n\\n /*\\n * @notice Check to see if there exists a request commitment consumers\\n * for all consumers and keyhashes for a given sub.\\n * @param subId - ID of the subscription\\n * @return true if there exists at least one unfulfilled request for the subscription, false\\n * otherwise.\\n */\\n function pendingRequestExists(uint256 subId) external view returns (bool);\\n\\n /**\\n * @notice Paginate through all active VRF subscriptions.\\n * @param startIndex index of the subscription to start from\\n * @param maxCount maximum number of subscriptions to return, 0 to return all\\n * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one\\n * @dev should consider keeping the blockheight constant to ensure a holistic picture of the contract state\\n */\\n function getActiveSubscriptionIds(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory);\\n\\n /**\\n * @notice Fund a subscription with native.\\n * @param subId - ID of the subscription\\n * @notice This method expects msg.value to be greater than or equal to 0.\\n */\\n function fundSubscriptionWithNative(uint256 subId) external payable;\\n}\\n\",\"keccak256\":\"0x85b348297ce36794e3bf97a47c001fc216bd0ee243e91514a7b395f3fcd189b0\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n// End consumer library.\\nlibrary VRFV2PlusClient {\\n // extraArgs will evolve to support new features\\n bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256(\\\"VRF ExtraArgsV1\\\"));\\n struct ExtraArgsV1 {\\n bool nativePayment;\\n }\\n\\n struct RandomWordsRequest {\\n bytes32 keyHash;\\n uint256 subId;\\n uint16 requestConfirmations;\\n uint32 callbackGasLimit;\\n uint32 numWords;\\n bytes extraArgs;\\n }\\n\\n function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {\\n return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs);\\n }\\n}\\n\",\"keccak256\":\"0x839ad7a737ef18147b518b4ec3cbaf4a49dc994db65cf8369ed4e69d169a98a6\",\"license\":\"MIT\"},\"src/rng/ChainlinkRNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport {VRFConsumerBaseV2Plus, IVRFCoordinatorV2Plus} from \\\"@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol\\\";\\nimport {VRFV2PlusClient} from \\\"@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol\\\";\\n\\nimport \\\"./RNG.sol\\\";\\n\\n/// @title Random Number Generator that uses Chainlink VRF v2.5\\n/// https://blog.chain.link/introducing-vrf-v2-5/\\ncontract ChainlinkRNG is RNG, VRFConsumerBaseV2Plus {\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n address public governor; // The address that can withdraw funds.\\n address public sortitionModule; // The address of the SortitionModule.\\n bytes32 public keyHash; // The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\\n uint256 public subscriptionId; // The unique identifier of the subscription used for funding requests.\\n uint16 public requestConfirmations; // How many confirmations the Chainlink node should wait before responding.\\n // 22 bytes remaining in slot\\n uint32 public callbackGasLimit; // Gas limit for the Chainlink callback.\\n uint256 lastRequestId; // The last request ID.\\n mapping(uint256 requestId => uint256 number) public randomNumbers; // randomNumbers[requestID] is the random number for this request id, 0 otherwise.\\n\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev Emitted when a request is sent to the VRF Coordinator\\n /// @param requestId The ID of the request\\n event RequestSent(uint256 indexed requestId);\\n\\n /// Emitted when a request has been fulfilled.\\n /// @param requestId The ID of the request\\n /// @param randomWord The random value answering the request.\\n event RequestFulfilled(uint256 indexed requestId, uint256 randomWord);\\n\\n // ************************************* //\\n // * Function Modifiers * //\\n // ************************************* //\\n\\n modifier onlyByGovernor() {\\n require(governor == msg.sender, \\\"Governor only\\\");\\n _;\\n }\\n\\n modifier onlyBySortitionModule() {\\n require(sortitionModule == msg.sender, \\\"SortitionModule only\\\");\\n _;\\n }\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor, initializing the implementation to reduce attack surface.\\n /// @param _governor The Governor of the contract.\\n /// @param _sortitionModule The address of the SortitionModule contract.\\n /// @param _vrfCoordinator The address of the VRFCoordinator contract.\\n /// @param _keyHash The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\\n /// @param _subscriptionId The unique identifier of the subscription used for funding requests.\\n /// @param _requestConfirmations How many confirmations the Chainlink node should wait before responding.\\n /// @param _callbackGasLimit The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.\\n /// @dev https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number\\n constructor(\\n address _governor,\\n address _sortitionModule,\\n address _vrfCoordinator,\\n bytes32 _keyHash,\\n uint256 _subscriptionId,\\n uint16 _requestConfirmations,\\n uint32 _callbackGasLimit\\n ) VRFConsumerBaseV2Plus(_vrfCoordinator) {\\n governor = _governor;\\n sortitionModule = _sortitionModule;\\n keyHash = _keyHash;\\n subscriptionId = _subscriptionId;\\n requestConfirmations = _requestConfirmations;\\n callbackGasLimit = _callbackGasLimit;\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n /// @dev Changes the governor of the contract.\\n /// @param _governor The new governor.\\n function changeGovernor(address _governor) external onlyByGovernor {\\n governor = _governor;\\n }\\n\\n /// @dev Changes the sortition module of the contract.\\n /// @param _sortitionModule The new sortition module.\\n function changeSortitionModule(address _sortitionModule) external onlyByGovernor {\\n sortitionModule = _sortitionModule;\\n }\\n\\n /// @dev Changes the VRF Coordinator of the contract.\\n /// @param _vrfCoordinator The new VRF Coordinator.\\n function changeVrfCoordinator(address _vrfCoordinator) external onlyByGovernor {\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n emit CoordinatorSet(_vrfCoordinator);\\n }\\n\\n /// @dev Changes the key hash of the contract.\\n /// @param _keyHash The new key hash.\\n function changeKeyHash(bytes32 _keyHash) external onlyByGovernor {\\n keyHash = _keyHash;\\n }\\n\\n /// @dev Changes the subscription ID of the contract.\\n /// @param _subscriptionId The new subscription ID.\\n function changeSubscriptionId(uint256 _subscriptionId) external onlyByGovernor {\\n subscriptionId = _subscriptionId;\\n }\\n\\n /// @dev Changes the request confirmations of the contract.\\n /// @param _requestConfirmations The new request confirmations.\\n function changeRequestConfirmations(uint16 _requestConfirmations) external onlyByGovernor {\\n requestConfirmations = _requestConfirmations;\\n }\\n\\n /// @dev Changes the callback gas limit of the contract.\\n /// @param _callbackGasLimit The new callback gas limit.\\n function changeCallbackGasLimit(uint32 _callbackGasLimit) external onlyByGovernor {\\n callbackGasLimit = _callbackGasLimit;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Request a random number. SortitionModule only.\\n function requestRandomness(uint256 /*_block*/) external override onlyBySortitionModule {\\n // Will revert if subscription is not set and funded.\\n uint256 requestId = s_vrfCoordinator.requestRandomWords(\\n VRFV2PlusClient.RandomWordsRequest({\\n keyHash: keyHash,\\n subId: subscriptionId,\\n requestConfirmations: requestConfirmations,\\n callbackGasLimit: callbackGasLimit,\\n numWords: 1,\\n extraArgs: VRFV2PlusClient._argsToBytes(\\n // Set nativePayment to true to pay for VRF requests with ETH instead of LINK\\n VRFV2PlusClient.ExtraArgsV1({nativePayment: true})\\n )\\n })\\n );\\n lastRequestId = requestId;\\n emit RequestSent(requestId);\\n }\\n\\n /// @dev Callback function called by the VRF Coordinator when the random value is generated.\\n /// @param _requestId The ID of the request.\\n /// @param _randomWords The random values answering the request.\\n function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) internal override {\\n // Access control is handled by the parent VRFCoordinator.rawFulfillRandomWords()\\n randomNumbers[_requestId] = _randomWords[0];\\n emit RequestFulfilled(_requestId, _randomWords[0]);\\n }\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @dev Return the random number.\\n /// @return randomNumber The random number or 0 if it is not ready or has not been requested.\\n function receiveRandomness(uint256 /*_block*/) external view override returns (uint256 randomNumber) {\\n randomNumber = randomNumbers[lastRequestId];\\n }\\n}\\n\",\"keccak256\":\"0xf7babff149b7892449b4346d637d1890cfaf579498d366598fff91fe1efcbfcc\",\"license\":\"MIT\"},\"src/rng/RNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\ninterface RNG {\\n /// @dev Request a random number.\\n /// @param _block Block linked to the request.\\n function requestRandomness(uint256 _block) external;\\n\\n /// @dev Receive the random number.\\n /// @param _block Block the random number is linked to.\\n /// @return randomNumber Random Number. If the number is not ready or has not been required 0 instead.\\n function receiveRandomness(uint256 _block) external returns (uint256 randomNumber);\\n}\\n\",\"keccak256\":\"0xf92e0cf768afefc5cc6ef786c263b67dd00c021aa5753213dbbc33014adb68c5\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162000f4c38038062000f4c83398101604081905262000034916200022d565b8433806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000165565b5050506001600160a01b038116620000ea5760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b03199081166001600160a01b03938416179091556003805482169983169990991790985560048054909816961695909517909555600591909155600655506007805461ffff90931665ffffffffffff19909316929092176201000063ffffffff90921691909102179055620002c5565b336001600160a01b03821603620001bf5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200022857600080fd5b919050565b600080600080600080600060e0888a0312156200024957600080fd5b620002548862000210565b9650620002646020890162000210565b9550620002746040890162000210565b9450606088015193506080880151925060a088015161ffff811681146200029a57600080fd5b60c089015190925063ffffffff81168114620002b557600080fd5b8091505092959891949750929550565b610c7780620002d56000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806379ba5097116100b8578063b0fb162f1161007c578063b0fb162f146102b9578063e4c0aaf4146102da578063e86a51cb146102ed578063f2fde38b14610300578063f50d390d14610313578063f9f5dd911461032657600080fd5b806379ba5097146102675780638da5cb5b1461026f5780638ea98117146102805780639eccacf614610293578063b0049637146102a657600080fd5b80632e1daf2f1161010a5780632e1daf2f146101f25780632f68f4821461020557806339b1e245146102185780635257cd901461022b57806361728f391461024b5780637363ae1f1461025457600080fd5b806309c1ba2e146101475780630c340a241461016357806313cf90541461018e5780631fe543e3146101b257806324f74697146101c7575b600080fd5b61015060065481565b6040519081526020015b60405180910390f35b600354610176906001600160a01b031681565b6040516001600160a01b03909116815260200161015a565b61015061019c366004610a3b565b5060085460009081526009602052604090205490565b6101c56101c0366004610a54565b610339565b005b6007546101dd9062010000900463ffffffff1681565b60405163ffffffff909116815260200161015a565b600454610176906001600160a01b031681565b6101c5610213366004610a3b565b61038e565b6101c5610226366004610a3b565b6103bd565b610150610239366004610a3b565b60096020526000908152604090205481565b61015060055481565b6101c5610262366004610a3b565b6103ec565b6101c5610547565b6000546001600160a01b0316610176565b6101c561028e366004610ad3565b6105f1565b600254610176906001600160a01b031681565b6101c56102b4366004610ad3565b6106e3565b6007546102c79061ffff1681565b60405161ffff909116815260200161015a565b6101c56102e8366004610ad3565b61072f565b6101c56102fb366004610b03565b61077b565b6101c561030e366004610ad3565b6107c9565b6101c5610321366004610b29565b6107dd565b6101c5610334366004610ad3565b61081f565b6002546001600160a01b0316331461037e5760025460405163073e64fd60e21b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b610389838383610849565b505050565b6003546001600160a01b031633146103b85760405162461bcd60e51b815260040161037590610b4d565b600555565b6003546001600160a01b031633146103e75760405162461bcd60e51b815260040161037590610b4d565b600655565b6004546001600160a01b0316331461043d5760405162461bcd60e51b8152602060048201526014602482015273536f72746974696f6e4d6f64756c65206f6e6c7960601b6044820152606401610375565b6002546040805160c081018252600554815260065460208083019190915260075461ffff81168385015262010000900463ffffffff16606083015260016080830181905283519182019093529182526000926001600160a01b031691639b1c385e919060a08201906104ae906108d2565b8152506040518263ffffffff1660e01b81526004016104cd9190610b74565b6020604051808303816000875af11580156104ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105109190610c12565b600881905560405190915081907f0cd21a41891ff04ecd9a8754bec97e2fb85d2a4e7694329d4dc364c796f23d0690600090a25050565b6001546001600160a01b0316331461059a5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610375565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331480159061061757506002546001600160a01b03163314155b15610668573361062f6000546001600160a01b031690565b60025460405163061db9c160e01b81526001600160a01b0393841660048201529183166024830152919091166044820152606401610375565b6001600160a01b03811661068f5760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be69060200160405180910390a150565b6003546001600160a01b0316331461070d5760405162461bcd60e51b815260040161037590610b4d565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107595760405162461bcd60e51b815260040161037590610b4d565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107a55760405162461bcd60e51b815260040161037590610b4d565b6007805463ffffffff909216620100000265ffffffff000019909216919091179055565b6107d1610943565b6107da81610998565b50565b6003546001600160a01b031633146108075760405162461bcd60e51b815260040161037590610b4d565b6007805461ffff191661ffff92909216919091179055565b6003546001600160a01b0316331461068f5760405162461bcd60e51b815260040161037590610b4d565b8181600081811061085c5761085c610c2b565b905060200201356009600085815260200190815260200160002081905550827f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d5838360008181106108af576108af610c2b565b905060200201356040516108c591815260200190565b60405180910390a2505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161090b91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000546001600160a01b031633146109965760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610375565b565b336001600160a01b038216036109ea5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610375565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a4d57600080fd5b5035919050565b600080600060408486031215610a6957600080fd5b83359250602084013567ffffffffffffffff80821115610a8857600080fd5b818601915086601f830112610a9c57600080fd5b813581811115610aab57600080fd5b8760208260051b8501011115610ac057600080fd5b6020830194508093505050509250925092565b600060208284031215610ae557600080fd5b81356001600160a01b0381168114610afc57600080fd5b9392505050565b600060208284031215610b1557600080fd5b813563ffffffff81168114610afc57600080fd5b600060208284031215610b3b57600080fd5b813561ffff81168114610afc57600080fd5b6020808252600d908201526c476f7665726e6f72206f6e6c7960981b604082015260600190565b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015610bed5782810184015186820161010001528301610bd0565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610c2457600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fdfea2646970667358221220b1b6124dbccf3f00c097f6ec7ed9e50782f84104bf8df5577b9728b9e27f9ed864736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101425760003560e01c806379ba5097116100b8578063b0fb162f1161007c578063b0fb162f146102b9578063e4c0aaf4146102da578063e86a51cb146102ed578063f2fde38b14610300578063f50d390d14610313578063f9f5dd911461032657600080fd5b806379ba5097146102675780638da5cb5b1461026f5780638ea98117146102805780639eccacf614610293578063b0049637146102a657600080fd5b80632e1daf2f1161010a5780632e1daf2f146101f25780632f68f4821461020557806339b1e245146102185780635257cd901461022b57806361728f391461024b5780637363ae1f1461025457600080fd5b806309c1ba2e146101475780630c340a241461016357806313cf90541461018e5780631fe543e3146101b257806324f74697146101c7575b600080fd5b61015060065481565b6040519081526020015b60405180910390f35b600354610176906001600160a01b031681565b6040516001600160a01b03909116815260200161015a565b61015061019c366004610a3b565b5060085460009081526009602052604090205490565b6101c56101c0366004610a54565b610339565b005b6007546101dd9062010000900463ffffffff1681565b60405163ffffffff909116815260200161015a565b600454610176906001600160a01b031681565b6101c5610213366004610a3b565b61038e565b6101c5610226366004610a3b565b6103bd565b610150610239366004610a3b565b60096020526000908152604090205481565b61015060055481565b6101c5610262366004610a3b565b6103ec565b6101c5610547565b6000546001600160a01b0316610176565b6101c561028e366004610ad3565b6105f1565b600254610176906001600160a01b031681565b6101c56102b4366004610ad3565b6106e3565b6007546102c79061ffff1681565b60405161ffff909116815260200161015a565b6101c56102e8366004610ad3565b61072f565b6101c56102fb366004610b03565b61077b565b6101c561030e366004610ad3565b6107c9565b6101c5610321366004610b29565b6107dd565b6101c5610334366004610ad3565b61081f565b6002546001600160a01b0316331461037e5760025460405163073e64fd60e21b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b610389838383610849565b505050565b6003546001600160a01b031633146103b85760405162461bcd60e51b815260040161037590610b4d565b600555565b6003546001600160a01b031633146103e75760405162461bcd60e51b815260040161037590610b4d565b600655565b6004546001600160a01b0316331461043d5760405162461bcd60e51b8152602060048201526014602482015273536f72746974696f6e4d6f64756c65206f6e6c7960601b6044820152606401610375565b6002546040805160c081018252600554815260065460208083019190915260075461ffff81168385015262010000900463ffffffff16606083015260016080830181905283519182019093529182526000926001600160a01b031691639b1c385e919060a08201906104ae906108d2565b8152506040518263ffffffff1660e01b81526004016104cd9190610b74565b6020604051808303816000875af11580156104ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105109190610c12565b600881905560405190915081907f0cd21a41891ff04ecd9a8754bec97e2fb85d2a4e7694329d4dc364c796f23d0690600090a25050565b6001546001600160a01b0316331461059a5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610375565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331480159061061757506002546001600160a01b03163314155b15610668573361062f6000546001600160a01b031690565b60025460405163061db9c160e01b81526001600160a01b0393841660048201529183166024830152919091166044820152606401610375565b6001600160a01b03811661068f5760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be69060200160405180910390a150565b6003546001600160a01b0316331461070d5760405162461bcd60e51b815260040161037590610b4d565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107595760405162461bcd60e51b815260040161037590610b4d565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107a55760405162461bcd60e51b815260040161037590610b4d565b6007805463ffffffff909216620100000265ffffffff000019909216919091179055565b6107d1610943565b6107da81610998565b50565b6003546001600160a01b031633146108075760405162461bcd60e51b815260040161037590610b4d565b6007805461ffff191661ffff92909216919091179055565b6003546001600160a01b0316331461068f5760405162461bcd60e51b815260040161037590610b4d565b8181600081811061085c5761085c610c2b565b905060200201356009600085815260200190815260200160002081905550827f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d5838360008181106108af576108af610c2b565b905060200201356040516108c591815260200190565b60405180910390a2505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161090b91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000546001600160a01b031633146109965760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610375565b565b336001600160a01b038216036109ea5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610375565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a4d57600080fd5b5035919050565b600080600060408486031215610a6957600080fd5b83359250602084013567ffffffffffffffff80821115610a8857600080fd5b818601915086601f830112610a9c57600080fd5b813581811115610aab57600080fd5b8760208260051b8501011115610ac057600080fd5b6020830194508093505050509250925092565b600060208284031215610ae557600080fd5b81356001600160a01b0381168114610afc57600080fd5b9392505050565b600060208284031215610b1557600080fd5b813563ffffffff81168114610afc57600080fd5b600060208284031215610b3b57600080fd5b813561ffff81168114610afc57600080fd5b6020808252600d908201526c476f7665726e6f72206f6e6c7960981b604082015260600190565b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015610bed5782810184015186820161010001528301610bd0565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610c2457600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fdfea2646970667358221220b1b6124dbccf3f00c097f6ec7ed9e50782f84104bf8df5577b9728b9e27f9ed864736f6c63430008180033", + "devdoc": { + "events": { + "RequestFulfilled(uint256,uint256)": { + "params": { + "randomWord": "The random value answering the request.", + "requestId": "The ID of the request" + } + }, + "RequestSent(uint256)": { + "details": "Emitted when a request is sent to the VRF Coordinator", + "params": { + "requestId": "The ID of the request" + } + } + }, + "kind": "dev", + "methods": { + "changeCallbackGasLimit(uint32)": { + "details": "Changes the callback gas limit of the contract.", + "params": { + "_callbackGasLimit": "The new callback gas limit." + } + }, + "changeGovernor(address)": { + "details": "Changes the governor of the contract.", + "params": { + "_governor": "The new governor." + } + }, + "changeKeyHash(bytes32)": { + "details": "Changes the key hash of the contract.", + "params": { + "_keyHash": "The new key hash." + } + }, + "changeRequestConfirmations(uint16)": { + "details": "Changes the request confirmations of the contract.", + "params": { + "_requestConfirmations": "The new request confirmations." + } + }, + "changeSortitionModule(address)": { + "details": "Changes the sortition module of the contract.", + "params": { + "_sortitionModule": "The new sortition module." + } + }, + "changeSubscriptionId(uint256)": { + "details": "Changes the subscription ID of the contract.", + "params": { + "_subscriptionId": "The new subscription ID." + } + }, + "changeVrfCoordinator(address)": { + "details": "Changes the VRF Coordinator of the contract.", + "params": { + "_vrfCoordinator": "The new VRF Coordinator." + } + }, + "constructor": { + "details": "Constructor, initializing the implementation to reduce attack surface.https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number", + "params": { + "_callbackGasLimit": "The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.", + "_governor": "The Governor of the contract.", + "_keyHash": "The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).", + "_requestConfirmations": "How many confirmations the Chainlink node should wait before responding.", + "_sortitionModule": "The address of the SortitionModule contract.", + "_subscriptionId": "The unique identifier of the subscription used for funding requests.", + "_vrfCoordinator": "The address of the VRFCoordinator contract." + } + }, + "receiveRandomness(uint256)": { + "details": "Return the random number.", + "returns": { + "randomNumber": "The random number or 0 if it is not ready or has not been requested." + } + }, + "requestRandomness(uint256)": { + "details": "Request a random number. SortitionModule only." + } + }, + "title": "Random Number Generator that uses Chainlink VRF v2.5 https://blog.chain.link/introducing-vrf-v2-5/", + "version": 1 + }, + "userdoc": { + "events": { + "RequestFulfilled(uint256,uint256)": { + "notice": "Emitted when a request has been fulfilled." + } + }, + "kind": "user", + "methods": { + "acceptOwnership()": { + "notice": "Allows an ownership transfer to be completed by the recipient." + }, + "owner()": { + "notice": "Get the current owner" + }, + "setCoordinator(address)": { + "notice": "Sets the VRF Coordinator addressThis method should only be callable by the coordinator or contract owner" + }, + "transferOwnership(address)": { + "notice": "Allows an owner to begin transferring ownership to a new address." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 29, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "s_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 31, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "s_pendingOwner", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 231, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "s_vrfCoordinator", + "offset": 0, + "slot": "2", + "type": "t_contract(IVRFCoordinatorV2Plus)380" + }, + { + "astId": 35404, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "governor", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 35406, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "sortitionModule", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 35408, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "keyHash", + "offset": 0, + "slot": "5", + "type": "t_bytes32" + }, + { + "astId": 35410, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "subscriptionId", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 35412, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "requestConfirmations", + "offset": 0, + "slot": "7", + "type": "t_uint16" + }, + { + "astId": 35414, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "callbackGasLimit", + "offset": 2, + "slot": "7", + "type": "t_uint32" + }, + { + "astId": 35416, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "lastRequestId", + "offset": 0, + "slot": "8", + "type": "t_uint256" + }, + { + "astId": 35420, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "randomNumbers", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_uint256,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IVRFCoordinatorV2Plus)380": { + "encoding": "inplace", + "label": "contract IVRFCoordinatorV2Plus", + "numberOfBytes": "20" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint16": { + "encoding": "inplace", + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + } + } + } +} diff --git a/contracts/deployments/arbitrumSepoliaDevnet/ChainlinkVRFCoordinator.json b/contracts/deployments/arbitrumSepoliaDevnet/ChainlinkVRFCoordinator.json new file mode 100644 index 000000000..0ad1f85b2 --- /dev/null +++ b/contracts/deployments/arbitrumSepoliaDevnet/ChainlinkVRFCoordinator.json @@ -0,0 +1,1753 @@ +{ + "address": "0x5CE8D5A2BC84beb22a398CCA51996F7930313D61", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "deregisterMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "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": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} diff --git a/contracts/src/rng/ChainlinkRNG.sol b/contracts/src/rng/ChainlinkRNG.sol index 41f2f770a..54883b283 100644 --- a/contracts/src/rng/ChainlinkRNG.sol +++ b/contracts/src/rng/ChainlinkRNG.sol @@ -21,7 +21,7 @@ contract ChainlinkRNG is RNG, VRFConsumerBaseV2Plus { uint16 public requestConfirmations; // How many confirmations the Chainlink node should wait before responding. // 22 bytes remaining in slot uint32 public callbackGasLimit; // Gas limit for the Chainlink callback. - uint256 lastRequestId; // The last request ID. + uint256 public lastRequestId; // The last request ID. mapping(uint256 requestId => uint256 number) public randomNumbers; // randomNumbers[requestID] is the random number for this request id, 0 otherwise. // ************************************* // From 2866a7a5f3dc47c036794be18be2bbfa1cf63777 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Mon, 9 Dec 2024 12:44:21 +0000 Subject: [PATCH 04/12] test: chainlink vrf testing with coordinator mock --- contracts/deploy/00-chainlink-rng.ts | 6 +- .../rng/mock/ChainlinkVRFCoordinatorMock.sol | 177 ++++++++++++++++++ contracts/test/rng/index.ts | 34 +++- 3 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol diff --git a/contracts/deploy/00-chainlink-rng.ts b/contracts/deploy/00-chainlink-rng.ts index 4ff7011e7..ade13b6fa 100644 --- a/contracts/deploy/00-chainlink-rng.ts +++ b/contracts/deploy/00-chainlink-rng.ts @@ -31,7 +31,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const SUBSCRIPTION_ID = { [HomeChains.ARBITRUM_ONE]: "66240499937595191069677958665918759554657443303079118766000192000140992834352", [HomeChains.ARBITRUM_SEPOLIA]: "38502597312983100069991953687934627561654236680431968938019951490339399569548", - [HomeChains.HARDHAT]: "0x0000000000000000000000000000000000000000000000000000000000000000", + [HomeChains.HARDHAT]: "0x0000000000000000000000000000000000000000000000000000000000000001", }; function getKeyHash({ gasPrice }: { gasPrice: keyof (typeof KEY_HASHES)[HomeChains.ARBITRUM_ONE] }): string { @@ -43,7 +43,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const ChainlinkVRFCoordinator = await getContractOrDeploy(hre, "ChainlinkVRFCoordinator", { from: deployer, - contract: "ChainlinkVRFCoordinator", + contract: "ChainlinkVRFCoordinatorV2Mock", args: [], log: true, }); @@ -57,7 +57,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) from: deployer, args: [ deployer, - deployer, + deployer, // For testing only, it should be the SortitionModule ChainlinkVRFCoordinator.target, keyHash, subscriptionId, diff --git a/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol b/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol new file mode 100644 index 000000000..c5ecd2b9d --- /dev/null +++ b/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {IVRFCoordinatorV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; +import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; + +/// @title A mock for testing code that relies on VRFCoordinatorV2. +contract ChainlinkVRFCoordinatorV2Mock is IVRFCoordinatorV2Plus { + // ************************************* // + // * Storage * // + // ************************************* // + + uint256 nextRequestId = 1; + mapping(uint256 requestID => VRFV2PlusClient.RandomWordsRequest request) requests; + + // ************************************* // + // * Events * // + // ************************************* // + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + address indexed sender + ); + event RandomWordsFulfilled(uint256 indexed requestId, bool success); + + // ************************************* // + // * Function Modifiers * // + // ************************************* // + + function fulfillRandomWords(uint256 _requestId, address _consumer, uint256[] memory _words) public { + if (requests[_requestId].subId == 0) { + revert("nonexistent request"); + } + VRFV2PlusClient.RandomWordsRequest memory req = requests[_requestId]; + + if (_words.length == 0) { + _words = new uint256[](req.numWords); + for (uint256 i = 0; i < req.numWords; i++) { + _words[i] = uint256(keccak256(abi.encode(_requestId, i))); + } + } else if (_words.length != req.numWords) { + revert InvalidRandomWords(); + } + + bytes4 FULFILL_RANDOM_WORDS_SELECTOR = bytes4(keccak256("rawFulfillRandomWords(uint256,uint256[])")); + bytes memory callReq = abi.encodeWithSelector(FULFILL_RANDOM_WORDS_SELECTOR, _requestId, _words); + (bool success, ) = _consumer.call{gas: req.callbackGasLimit}(callReq); + + delete (requests[_requestId]); + emit RandomWordsFulfilled(_requestId, success); + } + + function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256) { + uint256 requestId = nextRequestId++; + + requests[requestId] = req; + + emit RandomWordsRequested( + req.keyHash, + requestId, + req.subId, + req.requestConfirmations, + req.callbackGasLimit, + req.numWords, + msg.sender + ); + return requestId; + } + + // ************************************* // + // * Public Views * // + // ************************************* // + + function fundSubscription(uint256, uint96) public pure { + revert("not implemented"); + } + + function createSubscription() external pure returns (uint256) { + revert("not implemented"); + } + + function fundSubscriptionWithNative(uint256) external payable { + revert("not implemented"); + } + + function getActiveSubscriptionIds(uint256, uint256) external pure returns (uint256[] memory) { + revert("not implemented"); + } + + function getSubscription(uint256) external pure returns (uint96, uint96, uint64, address, address[] memory) { + revert("not implemented"); + } + + function cancelSubscription(uint256, address) external pure { + revert("not implemented"); + } + + function addConsumer(uint256, address) external pure { + revert("not implemented"); + } + + function removeConsumer(uint256, address) external pure { + revert("not implemented"); + } + + function getRequestConfig() external pure returns (uint16, uint32, bytes32[] memory) { + return (3, 2000000, new bytes32[](0)); + } + + function getConfig() + external + pure + returns ( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation + ) + { + return (4, 2_500_000, 2_700, 33285); + } + + function getFeeConfig() + external + pure + returns ( + uint32 fulfillmentFlatFeeLinkPPMTier1, + uint32 fulfillmentFlatFeeLinkPPMTier2, + uint32 fulfillmentFlatFeeLinkPPMTier3, + uint32 fulfillmentFlatFeeLinkPPMTier4, + uint32 fulfillmentFlatFeeLinkPPMTier5, + uint24 reqsForTier2, + uint24 reqsForTier3, + uint24 reqsForTier4, + uint24 reqsForTier5 + ) + { + return ( + 100000, // 0.1 LINK + 100000, // 0.1 LINK + 100000, // 0.1 LINK + 100000, // 0.1 LINK + 100000, // 0.1 LINK + 0, + 0, + 0, + 0 + ); + } + + function getFallbackWeiPerUnitLink() external pure returns (int256) { + return 4000000000000000; // 0.004 Ether + } + + function requestSubscriptionOwnerTransfer(uint256, address) external pure { + revert("not implemented"); + } + + function acceptSubscriptionOwnerTransfer(uint256) external pure { + revert("not implemented"); + } + + function pendingRequestExists(uint256) public pure returns (bool) { + revert("not implemented"); + } + + // ************************************* // + // * Errors * // + // ************************************* // + + error InvalidRandomWords(); +} diff --git a/contracts/test/rng/index.ts b/contracts/test/rng/index.ts index e11d4b8ff..3a34808f2 100644 --- a/contracts/test/rng/index.ts +++ b/contracts/test/rng/index.ts @@ -1,6 +1,6 @@ import { expect } from "chai"; -import { ethers, network } from "hardhat"; -import { IncrementalNG, BlockHashRNG } from "../../typechain-types"; +import { deployments, ethers, network } from "hardhat"; +import { IncrementalNG, BlockHashRNG, ChainlinkRNG, ChainlinkVRFCoordinatorV2Mock } from "../../typechain-types"; const initialNg = 424242; const abiCoder = ethers.AbiCoder.defaultAbiCoder(); @@ -46,3 +46,33 @@ describe("BlockHashRNG", async () => { expect(rn).to.equal(0); }); }); + +describe("ChainlinkRNG", async () => { + let rng: ChainlinkRNG; + let vrfCoordinator: ChainlinkVRFCoordinatorV2Mock; + + beforeEach("Setup", async () => { + await deployments.fixture(["ChainlinkRNG"], { + fallbackToGlobal: true, + keepExistingDeployments: false, + }); + rng = (await ethers.getContract("ChainlinkRNG")) as ChainlinkRNG; + vrfCoordinator = (await ethers.getContract("ChainlinkVRFCoordinator")) as ChainlinkVRFCoordinatorV2Mock; + }); + + it("Should return a non-zero random number", async () => { + const requestId = 1; + const expectedRn = BigInt( + ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(["uint256", "uint256"], [requestId, 0])) + ); + + let tx = await rng.requestRandomness(0); + await expect(tx).to.emit(rng, "RequestSent").withArgs(requestId); + + tx = await vrfCoordinator.fulfillRandomWords(requestId, rng.target, []); + await expect(tx).to.emit(rng, "RequestFulfilled").withArgs(requestId, expectedRn); + + const rn = await rng.receiveRandomness(0); + expect(rn).to.equal(expectedRn); + }); +}); From 3f2baa0250a107155b7c2cfa92fcb01add0d3e73 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 11 Dec 2024 13:08:53 +0000 Subject: [PATCH 05/12] chore: randomizer rng does not need to be upgradable --- .../deploy/00-home-chain-arbitration-neo.ts | 2 +- contracts/deploy/00-home-chain-arbitration.ts | 2 +- contracts/deploy/00-rng.ts | 2 +- contracts/src/rng/RandomizerRNG.sol | 25 ++-------- .../rng/mock/ChainlinkVRFCoordinatorMock.sol | 49 ------------------- 5 files changed, 6 insertions(+), 74 deletions(-) diff --git a/contracts/deploy/00-home-chain-arbitration-neo.ts b/contracts/deploy/00-home-chain-arbitration-neo.ts index ce4105f04..ee22f3975 100644 --- a/contracts/deploy/00-home-chain-arbitration-neo.ts +++ b/contracts/deploy/00-home-chain-arbitration-neo.ts @@ -36,7 +36,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) log: true, }); - const rng = await deployUpgradable(deployments, "RandomizerRNG", { + const rng = await deploy("RandomizerRNG", { from: deployer, args: [deployer, ZeroAddress, randomizerOracle.target], // The SortitionModule is configured later log: true, diff --git a/contracts/deploy/00-home-chain-arbitration.ts b/contracts/deploy/00-home-chain-arbitration.ts index b1cc2c6b7..ec064cf0f 100644 --- a/contracts/deploy/00-home-chain-arbitration.ts +++ b/contracts/deploy/00-home-chain-arbitration.ts @@ -36,7 +36,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) log: true, }); - const randomizerRng = await getContractOrDeployUpgradable(hre, "RandomizerRNG", { + const randomizerRng = await getContractOrDeploy(hre, "RandomizerRNG", { from: deployer, args: [deployer, ZeroAddress, randomizerOracle.target], // The SortitionModule is configured later log: true, diff --git a/contracts/deploy/00-rng.ts b/contracts/deploy/00-rng.ts index 269244ef9..2489406c1 100644 --- a/contracts/deploy/00-rng.ts +++ b/contracts/deploy/00-rng.ts @@ -24,7 +24,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) log: true, }); - const rng1 = await deployUpgradable(deployments, "RandomizerRNG", { + const rng1 = await deploy("RandomizerRNG", { from: deployer, args: [deployer, sortitionModule.target, randomizerOracle.address], log: true, diff --git a/contracts/src/rng/RandomizerRNG.sol b/contracts/src/rng/RandomizerRNG.sol index 6849247d6..a8b4c8b41 100644 --- a/contracts/src/rng/RandomizerRNG.sol +++ b/contracts/src/rng/RandomizerRNG.sol @@ -4,12 +4,10 @@ pragma solidity 0.8.24; import "./RNG.sol"; import "./IRandomizer.sol"; -import "../proxy/UUPSProxiable.sol"; -import "../proxy/Initializable.sol"; /// @title Random Number Generator that uses Randomizer.ai /// https://randomizer.ai/ -contract RandomizerRNG is RNG, UUPSProxiable, Initializable { +contract RandomizerRNG is RNG { // ************************************* // // * Storage * // // ************************************* // @@ -52,19 +50,10 @@ contract RandomizerRNG is RNG, UUPSProxiable, Initializable { // * Constructor * // // ************************************* // - /// @dev Constructor, initializing the implementation to reduce attack surface. - constructor() { - _disableInitializers(); - } - - /// @dev Initializer + /// @dev Constructor /// @param _randomizer Randomizer contract. /// @param _governor Governor of the contract. - function initialize( - address _governor, - address _sortitionModule, - IRandomizer _randomizer - ) external reinitializer(1) { + constructor(address _governor, address _sortitionModule, IRandomizer _randomizer) { governor = _governor; sortitionModule = _sortitionModule; randomizer = _randomizer; @@ -75,14 +64,6 @@ contract RandomizerRNG is RNG, UUPSProxiable, Initializable { // * Governance * // // ************************ // - /** - * @dev Access Control to perform implementation upgrades (UUPS Proxiable) - * @dev Only the governor can perform upgrades (`onlyByGovernor`) - */ - function _authorizeUpgrade(address) internal view override onlyByGovernor { - // NOP - } - /// @dev Changes the governor of the contract. /// @param _governor The new governor. function changeGovernor(address _governor) external onlyByGovernor { diff --git a/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol b/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol index c5ecd2b9d..c78dc3798 100644 --- a/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol +++ b/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol @@ -108,55 +108,6 @@ contract ChainlinkVRFCoordinatorV2Mock is IVRFCoordinatorV2Plus { revert("not implemented"); } - function getRequestConfig() external pure returns (uint16, uint32, bytes32[] memory) { - return (3, 2000000, new bytes32[](0)); - } - - function getConfig() - external - pure - returns ( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation - ) - { - return (4, 2_500_000, 2_700, 33285); - } - - function getFeeConfig() - external - pure - returns ( - uint32 fulfillmentFlatFeeLinkPPMTier1, - uint32 fulfillmentFlatFeeLinkPPMTier2, - uint32 fulfillmentFlatFeeLinkPPMTier3, - uint32 fulfillmentFlatFeeLinkPPMTier4, - uint32 fulfillmentFlatFeeLinkPPMTier5, - uint24 reqsForTier2, - uint24 reqsForTier3, - uint24 reqsForTier4, - uint24 reqsForTier5 - ) - { - return ( - 100000, // 0.1 LINK - 100000, // 0.1 LINK - 100000, // 0.1 LINK - 100000, // 0.1 LINK - 100000, // 0.1 LINK - 0, - 0, - 0, - 0 - ); - } - - function getFallbackWeiPerUnitLink() external pure returns (int256) { - return 4000000000000000; // 0.004 Ether - } - function requestSubscriptionOwnerTransfer(uint256, address) external pure { revert("not implemented"); } From 555f04ae3f8e3fd1adc3f557564ec8c98afc0c93 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 11 Dec 2024 13:15:41 +0000 Subject: [PATCH 06/12] feat: added support for the chainlink rng in the keeper bot --- contracts/scripts/keeperBot.ts | 22 +++++++++++++++++----- contracts/src/rng/RandomizerRNG.sol | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/contracts/scripts/keeperBot.ts b/contracts/scripts/keeperBot.ts index 34633f3bf..356c7332e 100644 --- a/contracts/scripts/keeperBot.ts +++ b/contracts/scripts/keeperBot.ts @@ -7,6 +7,7 @@ import { KlerosCoreNeo, SortitionModuleNeo, DisputeKitClassic, + ChainlinkRNG, } from "../typechain-types"; import request from "graphql-request"; import env from "./utils/env"; @@ -61,10 +62,11 @@ const getContracts = async () => { default: throw new Error("Invalid core type, must be one of base, neo"); } + const chainlinkRng = await ethers.getContractOrNull("ChainlinkRNG"); const randomizerRng = await ethers.getContractOrNull("RandomizerRNG"); const blockHashRNG = await ethers.getContractOrNull("BlockHashRNG"); const pnk = (await ethers.getContract("PNK")) as PNK; - return { core, sortition, randomizerRng, blockHashRNG, disputeKitClassic, pnk }; + return { core, sortition, chainlinkRng, randomizerRng, blockHashRNG, disputeKitClassic, pnk }; }; type Contribution = { @@ -181,11 +183,21 @@ const handleError = (e: any) => { }; const isRngReady = async () => { - const { randomizerRng, blockHashRNG, sortition } = await getContracts(); + const { chainlinkRng, randomizerRng, blockHashRNG, sortition } = await getContracts(); const currentRng = await sortition.rng(); - if (currentRng === randomizerRng?.target) { - const requesterID = await randomizerRng.requesterToID(sortition.target); - const n = await randomizerRng.randomNumbers(requesterID); + if (currentRng === chainlinkRng?.target) { + const requestID = await chainlinkRng.lastRequestId(); + const n = await chainlinkRng.randomNumbers(requestID); + if (Number(n) === 0) { + logger.info("ChainlinkRNG is NOT ready yet"); + return false; + } else { + logger.info(`ChainlinkRNG is ready: ${n.toString()}`); + return true; + } + } else if (currentRng === randomizerRng?.target) { + const requestID = await randomizerRng.lastRequestId(); + const n = await randomizerRng.randomNumbers(requestID); if (Number(n) === 0) { logger.info("RandomizerRNG is NOT ready yet"); return false; diff --git a/contracts/src/rng/RandomizerRNG.sol b/contracts/src/rng/RandomizerRNG.sol index a8b4c8b41..248379af0 100644 --- a/contracts/src/rng/RandomizerRNG.sol +++ b/contracts/src/rng/RandomizerRNG.sol @@ -16,7 +16,7 @@ contract RandomizerRNG is RNG { address public sortitionModule; // The address of the SortitionModule. IRandomizer public randomizer; // Randomizer address. uint256 public callbackGasLimit; // Gas limit for the Randomizer.ai callback. - uint256 lastRequestId; // The last request ID. + uint256 public lastRequestId; // The last request ID. mapping(uint256 requestId => uint256 number) public randomNumbers; // randomNumbers[requestID] is the random number for this request id, 0 otherwise. // ************************************* // From 0e2264a7506623f48188be467c5acee30e69ab2f Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 11 Dec 2024 13:32:15 +0000 Subject: [PATCH 07/12] chore: deploy scripts now use the chainlink rng --- contracts/deploy/00-chainlink-rng.ts | 10 ++--- contracts/deploy/00-home-chain-arbitrable.ts | 1 - .../deploy/00-home-chain-arbitration-neo.ts | 26 ++++--------- contracts/deploy/00-home-chain-arbitration.ts | 37 ++++--------------- contracts/deploy/00-randomizer-rng.ts | 35 ++++++++++++++++++ 5 files changed, 54 insertions(+), 55 deletions(-) create mode 100644 contracts/deploy/00-randomizer-rng.ts diff --git a/contracts/deploy/00-chainlink-rng.ts b/contracts/deploy/00-chainlink-rng.ts index ade13b6fa..bc1508ed8 100644 --- a/contracts/deploy/00-chainlink-rng.ts +++ b/contracts/deploy/00-chainlink-rng.ts @@ -3,7 +3,7 @@ import { DeployFunction } from "hardhat-deploy/types"; import { HomeChains, isSkipped } from "./utils"; import { getContractOrDeploy } from "./utils/getContractOrDeploy"; -const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { +const deployRng: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const { deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; @@ -57,7 +57,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) from: deployer, args: [ deployer, - deployer, // For testing only, it should be the SortitionModule + deployer, // The consumer is configured as the SortitionModule later ChainlinkVRFCoordinator.target, keyHash, subscriptionId, @@ -68,9 +68,9 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) }); }; -deployArbitration.tags = ["ChainlinkRNG"]; -deployArbitration.skip = async ({ network }) => { +deployRng.tags = ["ChainlinkRNG"]; +deployRng.skip = async ({ network }) => { return isSkipped(network, !HomeChains[network.config.chainId ?? 0]); }; -export default deployArbitration; +export default deployRng; diff --git a/contracts/deploy/00-home-chain-arbitrable.ts b/contracts/deploy/00-home-chain-arbitrable.ts index 458a74b21..7d3f287a5 100644 --- a/contracts/deploy/00-home-chain-arbitrable.ts +++ b/contracts/deploy/00-home-chain-arbitrable.ts @@ -1,6 +1,5 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; -import disputeTemplate from "../test/fixtures/DisputeTemplate.simple.json"; import { HomeChains, isSkipped } from "./utils"; import { deployUpgradable } from "./utils/deployUpgradable"; diff --git a/contracts/deploy/00-home-chain-arbitration-neo.ts b/contracts/deploy/00-home-chain-arbitration-neo.ts index ee22f3975..bdddaa999 100644 --- a/contracts/deploy/00-home-chain-arbitration-neo.ts +++ b/contracts/deploy/00-home-chain-arbitration-neo.ts @@ -6,7 +6,7 @@ import { changeCurrencyRate } from "./utils/klerosCoreHelper"; import { HomeChains, isSkipped, isDevnet, PNK, ETH } from "./utils"; import { getContractOrDeploy, getContractOrDeployUpgradable } from "./utils/getContractOrDeploy"; import { deployERC20AndFaucet, deployERC721 } from "./utils/deployTokens"; -import { DisputeKitClassic, KlerosCoreNeo, RandomizerRNG } from "../typechain-types"; +import { ChainlinkRNG, DisputeKitClassic, KlerosCoreNeo, RandomizerRNG } from "../typechain-types"; const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const { ethers, deployments, getNamedAccounts, getChainId } = hre; @@ -29,19 +29,6 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) await deployUpgradable(deployments, "EvidenceModule", { from: deployer, args: [deployer], log: true }); - const randomizerOracle = await getContractOrDeploy(hre, "RandomizerOracle", { - from: deployer, - contract: "RandomizerMock", - args: [], - log: true, - }); - - const rng = await deploy("RandomizerRNG", { - from: deployer, - args: [deployer, ZeroAddress, randomizerOracle.target], // The SortitionModule is configured later - log: true, - }); - const disputeKit = await deployUpgradable(deployments, "DisputeKitClassicNeo", { from: deployer, contract: "DisputeKitClassic", @@ -58,6 +45,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const devnet = isDevnet(hre.network); const minStakingTime = devnet ? 180 : 1800; const maxFreezingTime = devnet ? 600 : 1800; + const rng = (await ethers.getContract("ChainlinkRNG")) as ChainlinkRNG; const maxStakePerJuror = PNK(2_000); const maxTotalStaked = PNK(2_000_000); const sortitionModule = await deployUpgradable(deployments, "SortitionModuleNeo", { @@ -67,7 +55,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) klerosCoreAddress, minStakingTime, maxFreezingTime, - rng.address, + rng.target, RNG_LOOKAHEAD, maxStakePerJuror, maxTotalStaked, @@ -106,11 +94,10 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) } // rng.changeSortitionModule() only if necessary - const rngContract = (await ethers.getContract("RandomizerRNG")) as RandomizerRNG; - const currentSortitionModule = await rngContract.sortitionModule(); - if (currentSortitionModule !== sortitionModule.address) { + const rngSortitionModule = await rng.sortitionModule(); + if (rngSortitionModule !== sortitionModule.address) { console.log(`rng.changeSortitionModule(${sortitionModule.address})`); - await rngContract.changeSortitionModule(sortitionModule.address); + await rng.changeSortitionModule(sortitionModule.address); } const core = (await hre.ethers.getContract("KlerosCoreNeo")) as KlerosCoreNeo; @@ -138,6 +125,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) }; deployArbitration.tags = ["ArbitrationNeo"]; +deployArbitration.dependencies = ["ChainlinkRNG"]; deployArbitration.skip = async ({ network }) => { return isSkipped(network, !HomeChains[network.config.chainId ?? 0]); }; diff --git a/contracts/deploy/00-home-chain-arbitration.ts b/contracts/deploy/00-home-chain-arbitration.ts index ec064cf0f..559453910 100644 --- a/contracts/deploy/00-home-chain-arbitration.ts +++ b/contracts/deploy/00-home-chain-arbitration.ts @@ -3,10 +3,10 @@ import { DeployFunction } from "hardhat-deploy/types"; import { getContractAddress } from "./utils/getContractAddress"; import { deployUpgradable } from "./utils/deployUpgradable"; import { changeCurrencyRate } from "./utils/klerosCoreHelper"; -import { HomeChains, isSkipped, isDevnet, isMainnet, PNK, ETH } from "./utils"; +import { HomeChains, isSkipped, isDevnet, PNK, ETH } from "./utils"; import { getContractOrDeploy, getContractOrDeployUpgradable } from "./utils/getContractOrDeploy"; import { deployERC20AndFaucet } from "./utils/deployTokens"; -import { DisputeKitClassic, KlerosCore, RandomizerRNG } from "../typechain-types"; +import { ChainlinkRNG, DisputeKitClassic, KlerosCore } from "../typechain-types"; const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const { ethers, deployments, getNamedAccounts, getChainId } = hre; @@ -28,30 +28,6 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) await getContractOrDeployUpgradable(hre, "EvidenceModule", { from: deployer, args: [deployer], log: true }); - // Randomizer.ai: https://randomizer.ai/docs#addresses - const randomizerOracle = await getContractOrDeploy(hre, "RandomizerOracle", { - from: deployer, - contract: "RandomizerMock", // The mock is deployed only on the Hardhat network - args: [], - log: true, - }); - - const randomizerRng = await getContractOrDeploy(hre, "RandomizerRNG", { - from: deployer, - args: [deployer, ZeroAddress, randomizerOracle.target], // The SortitionModule is configured later - log: true, - }); - - const blockhashRng = await getContractOrDeploy(hre, "BlockHashRNG", { - from: deployer, - args: [], - log: true, - }); - - // RNG fallback on Arbitrum Sepolia because the Randomizer.ai oracle contract is unverified and not officially supported. - const rng = isMainnet(hre.network) ? randomizerRng : blockhashRng; - console.log(isMainnet(hre.network) ? "using RandomizerRNG on mainnet" : "using BlockHashRNG on testnet/devnet"); - const disputeKit = await deployUpgradable(deployments, "DisputeKitClassic", { from: deployer, args: [deployer, ZeroAddress], @@ -67,6 +43,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const devnet = isDevnet(hre.network); const minStakingTime = devnet ? 180 : 1800; const maxFreezingTime = devnet ? 600 : 1800; + const rng = (await ethers.getContract("ChainlinkRNG")) as ChainlinkRNG; const sortitionModule = await deployUpgradable(deployments, "SortitionModule", { from: deployer, args: [deployer, klerosCoreAddress, minStakingTime, maxFreezingTime, rng.target, RNG_LOOKAHEAD], @@ -103,11 +80,10 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) } // rng.changeSortitionModule() only if necessary - const rngContract = (await ethers.getContract("RandomizerRNG")) as RandomizerRNG; - const currentSortitionModule = await rngContract.sortitionModule(); - if (currentSortitionModule !== sortitionModule.address) { + const rngSortitionModule = await rng.sortitionModule(); + if (rngSortitionModule !== sortitionModule.address) { console.log(`rng.changeSortitionModule(${sortitionModule.address})`); - await rngContract.changeSortitionModule(sortitionModule.address); + await rng.changeSortitionModule(sortitionModule.address); } const core = (await hre.ethers.getContract("KlerosCore")) as KlerosCore; @@ -121,6 +97,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) }; deployArbitration.tags = ["Arbitration"]; +deployArbitration.dependencies = ["ChainlinkRNG"]; deployArbitration.skip = async ({ network }) => { return isSkipped(network, !HomeChains[network.config.chainId ?? 0]); }; diff --git a/contracts/deploy/00-randomizer-rng.ts b/contracts/deploy/00-randomizer-rng.ts new file mode 100644 index 000000000..c28dc3cda --- /dev/null +++ b/contracts/deploy/00-randomizer-rng.ts @@ -0,0 +1,35 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HomeChains, isSkipped } from "./utils"; +import { getContractOrDeploy } from "./utils/getContractOrDeploy"; + +const deployRng: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { + const { deployments, getNamedAccounts, getChainId } = hre; + const { deploy } = deployments; + + // fallback to hardhat node signers on local network + const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address; + const chainId = Number(await getChainId()) as unknown as HomeChains; // Checked at runtime by skip() + console.log("deploying to %s with deployer %s", HomeChains[chainId], deployer); + + // Randomizer.ai: https://randomizer.ai/docs#addresses + const randomizerOracle = await getContractOrDeploy(hre, "RandomizerOracle", { + from: deployer, + contract: "RandomizerMock", // The mock is deployed only on the Hardhat network + args: [], + log: true, + }); + + await getContractOrDeploy(hre, "RandomizerRNG", { + from: deployer, + args: [deployer, deployer, randomizerOracle.target], // The consumer is configured as the SortitionModule later + log: true, + }); +}; + +deployRng.tags = ["RandomizerRNG"]; +deployRng.skip = async ({ network }) => { + return isSkipped(network, !HomeChains[network.config.chainId ?? 0]); +}; + +export default deployRng; From eabb03b658dd8e2d795579ba32b1b3fa3aacd37b Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 11 Dec 2024 13:40:04 +0000 Subject: [PATCH 08/12] chore: chainlink RNG deployed, not used by the sortition module yet --- contracts/README.md | 7 + .../deployments/arbitrum/ChainlinkRNG.json | 749 ++++++++++++++++++ .../arbitrumSepolia/ChainlinkRNG.json | 749 ++++++++++++++++++ .../arbitrumSepoliaDevnet/ChainlinkRNG.json | 41 +- 4 files changed, 1532 insertions(+), 14 deletions(-) create mode 100644 contracts/deployments/arbitrum/ChainlinkRNG.json create mode 100644 contracts/deployments/arbitrumSepolia/ChainlinkRNG.json diff --git a/contracts/README.md b/contracts/README.md index 7b9441882..93a74935c 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -10,6 +10,9 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments #### Arbitrum One +- [BlockHashRNG](https://arbiscan.io/address/0x39D123fc4cFD24EA5bB76195f9ecFE1f0DF35b0B) +- [ChainlinkRNG](https://arbiscan.io/address/0x897d83a7d5F23555eFA15e1BE297d5503522cbA3) +- [ChainlinkVRFCoordinator](https://arbiscan.io/address/0xf97f4df75117a78c1A5a0DBb814Af92458539FB4) - [DisputeKitClassicNeo: proxy](https://arbiscan.io/address/0x70B464be85A547144C72485eBa2577E5D3A45421), [implementation](https://arbiscan.io/address/0xAF0325dbBFa812a574743Bb5A085266D31e3e03a) - [DisputeResolverNeo](https://arbiscan.io/address/0xb5526D022962A1fFf6eD32C93e8b714c901F4323) - [DisputeTemplateRegistry: proxy](https://arbiscan.io/address/0x0cFBaCA5C72e7Ca5fFABE768E135654fB3F2a5A2), [implementation](https://arbiscan.io/address/0x57EfD43DAfCeb6C58Df57932b2B299f46fef5c87) @@ -27,6 +30,8 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments #### Arbitrum Sepolia - [BlockHashRNG](https://sepolia.arbiscan.io/address/0x0298a3EFa6Faf90865725E2b48Cf0F66e5d52754) +- [ChainlinkRNG](https://sepolia.arbiscan.io/address/0xAd5cCc93429e3A977c273cEeD106Ef16A69EAf79) +- [ChainlinkVRFCoordinator](https://sepolia.arbiscan.io/address/0x5CE8D5A2BC84beb22a398CCA51996F7930313D61) - [DAI](https://sepolia.arbiscan.io/address/0xc34aeFEa232956542C5b2f2EE55fD5c378B35c03) - [DAIFaucet](https://sepolia.arbiscan.io/address/0x1Fa58B52326488D62A406E71DBaD839560e810fF) - [DisputeKitClassic: proxy](https://sepolia.arbiscan.io/address/0x0c38f115D001d3b5bBec5e8D44f78C7B61A27D94), [implementation](https://sepolia.arbiscan.io/address/0xDb0B7908C46E2Bb08459bf9b3155b9bb8F8713E1) @@ -67,6 +72,8 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments - [ArbitrableExample](https://sepolia.arbiscan.io/address/0x3Eae72F076c68F5c354C73abC33EAA291ef1b2Fa) - [BlockHashRNG](https://sepolia.arbiscan.io/address/0x56d6d65Fe202232714794B5D5e4ed9894466Ee01) +- [ChainlinkRNG](https://sepolia.arbiscan.io/address/0x6c40D7F5d5bE3492fe9EF70e4eCb2BD773c12AF8) +- [ChainlinkVRFCoordinator](https://sepolia.arbiscan.io/address/0x5CE8D5A2BC84beb22a398CCA51996F7930313D61) - [DAI](https://sepolia.arbiscan.io/address/0x593e89704D285B0c3fbF157c7CF2537456CE64b5) - [DAIFaucet](https://sepolia.arbiscan.io/address/0xB5b39A1bcD2D7097A8824B3cC18Ebd2dFb0D9B5E) - [DisputeKitClassic: proxy](https://sepolia.arbiscan.io/address/0x9426F127116C3652A262AE1eA48391AC8F44D35b), [implementation](https://sepolia.arbiscan.io/address/0x692CC78F2570181FFB99297965FeAA8352ab12E8) diff --git a/contracts/deployments/arbitrum/ChainlinkRNG.json b/contracts/deployments/arbitrum/ChainlinkRNG.json new file mode 100644 index 000000000..694e7396e --- /dev/null +++ b/contracts/deployments/arbitrum/ChainlinkRNG.json @@ -0,0 +1,749 @@ +{ + "address": "0x897d83a7d5F23555eFA15e1BE297d5503522cbA3", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + }, + { + "internalType": "address", + "name": "_sortitionModule", + "type": "address" + }, + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_subscriptionId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "randomWord", + "type": "uint256" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "callbackGasLimit", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + } + ], + "name": "changeCallbackGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "changeGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + } + ], + "name": "changeKeyHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + } + ], + "name": "changeRequestConfirmations", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_sortitionModule", + "type": "address" + } + ], + "name": "changeSortitionModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_subscriptionId", + "type": "uint256" + } + ], + "name": "changeSubscriptionId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "changeVrfCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "randomNumbers", + "outputs": [ + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "receiveRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "randomNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "requestConfirmations", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "requestRandomness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sortitionModule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subscriptionId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xe836e09161f9bedd5874f29ca3869b3c274962e386177b13dedf159b3baec588", + "receipt": { + "to": null, + "from": "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "contractAddress": "0x897d83a7d5F23555eFA15e1BE297d5503522cbA3", + "transactionIndex": 1, + "gasUsed": "1048593", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x2a5ba9c10406df82a46799081e8833ecaab8682bddbdce9c30b891706649721f", + "transactionHash": "0xe836e09161f9bedd5874f29ca3869b3c274962e386177b13dedf159b3baec588", + "logs": [], + "blockNumber": 283670668, + "cumulativeGasUsed": "1048593", + "status": 1, + "byzantium": true + }, + "args": [ + "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", + "0xe9f223d7d83ec85c4f78042a4845af3a1c8df7757b4997b815ce4b8d07aca68c", + "66240499937595191069677958665918759554657443303079118766000192000140992834352", + 200, + 100000 + ], + "numDeployments": 1, + "solcInputHash": "409820253ec776b564318c3061b7e926", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_sortitionModule\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_subscriptionId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"want\",\"type\":\"address\"}],\"name\":\"OnlyCoordinatorCanFulfill\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"OnlyOwnerOrCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vrfCoordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"randomWord\",\"type\":\"uint256\"}],\"name\":\"RequestFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"RequestSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"callbackGasLimit\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"name\":\"changeCallbackGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"}],\"name\":\"changeKeyHash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"}],\"name\":\"changeRequestConfirmations\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sortitionModule\",\"type\":\"address\"}],\"name\":\"changeSortitionModule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_subscriptionId\",\"type\":\"uint256\"}],\"name\":\"changeSubscriptionId\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"changeVrfCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"keyHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastRequestId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"randomNumbers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"receiveRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"randomNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requestConfirmations\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"requestRandomness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_vrfCoordinator\",\"outputs\":[{\"internalType\":\"contract IVRFCoordinatorV2Plus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sortitionModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"subscriptionId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"RequestFulfilled(uint256,uint256)\":{\"params\":{\"randomWord\":\"The random value answering the request.\",\"requestId\":\"The ID of the request\"}},\"RequestSent(uint256)\":{\"details\":\"Emitted when a request is sent to the VRF Coordinator\",\"params\":{\"requestId\":\"The ID of the request\"}}},\"kind\":\"dev\",\"methods\":{\"changeCallbackGasLimit(uint32)\":{\"details\":\"Changes the callback gas limit of the contract.\",\"params\":{\"_callbackGasLimit\":\"The new callback gas limit.\"}},\"changeGovernor(address)\":{\"details\":\"Changes the governor of the contract.\",\"params\":{\"_governor\":\"The new governor.\"}},\"changeKeyHash(bytes32)\":{\"details\":\"Changes the key hash of the contract.\",\"params\":{\"_keyHash\":\"The new key hash.\"}},\"changeRequestConfirmations(uint16)\":{\"details\":\"Changes the request confirmations of the contract.\",\"params\":{\"_requestConfirmations\":\"The new request confirmations.\"}},\"changeSortitionModule(address)\":{\"details\":\"Changes the sortition module of the contract.\",\"params\":{\"_sortitionModule\":\"The new sortition module.\"}},\"changeSubscriptionId(uint256)\":{\"details\":\"Changes the subscription ID of the contract.\",\"params\":{\"_subscriptionId\":\"The new subscription ID.\"}},\"changeVrfCoordinator(address)\":{\"details\":\"Changes the VRF Coordinator of the contract.\",\"params\":{\"_vrfCoordinator\":\"The new VRF Coordinator.\"}},\"constructor\":{\"details\":\"Constructor, initializing the implementation to reduce attack surface.https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number\",\"params\":{\"_callbackGasLimit\":\"The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.\",\"_governor\":\"The Governor of the contract.\",\"_keyHash\":\"The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\",\"_requestConfirmations\":\"How many confirmations the Chainlink node should wait before responding.\",\"_sortitionModule\":\"The address of the SortitionModule contract.\",\"_subscriptionId\":\"The unique identifier of the subscription used for funding requests.\",\"_vrfCoordinator\":\"The address of the VRFCoordinator contract.\"}},\"receiveRandomness(uint256)\":{\"details\":\"Return the random number.\",\"returns\":{\"randomNumber\":\"The random number or 0 if it is not ready or has not been requested.\"}},\"requestRandomness(uint256)\":{\"details\":\"Request a random number. SortitionModule only.\"}},\"title\":\"Random Number Generator that uses Chainlink VRF v2.5 https://blog.chain.link/introducing-vrf-v2-5/\",\"version\":1},\"userdoc\":{\"events\":{\"RequestFulfilled(uint256,uint256)\":{\"notice\":\"Emitted when a request has been fulfilled.\"}},\"kind\":\"user\",\"methods\":{\"acceptOwnership()\":{\"notice\":\"Allows an ownership transfer to be completed by the recipient.\"},\"owner()\":{\"notice\":\"Get the current owner\"},\"setCoordinator(address)\":{\"notice\":\"Sets the VRF Coordinator addressThis method should only be callable by the coordinator or contract owner\"},\"transferOwnership(address)\":{\"notice\":\"Allows an owner to begin transferring ownership to a new address.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/rng/ChainlinkRNG.sol\":\"ChainlinkRNG\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {ConfirmedOwnerWithProposal} from \\\"./ConfirmedOwnerWithProposal.sol\\\";\\n\\n/// @title The ConfirmedOwner contract\\n/// @notice A contract with helpers for basic contract ownership.\\ncontract ConfirmedOwner is ConfirmedOwnerWithProposal {\\n constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}\\n}\\n\",\"keccak256\":\"0xdcb0e9135ddbe71ee27ba99fa06656960c66c964cf2ecb29696da1c1427d9861\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {IOwnable} from \\\"../interfaces/IOwnable.sol\\\";\\n\\n/// @title The ConfirmedOwner contract\\n/// @notice A contract with helpers for basic contract ownership.\\ncontract ConfirmedOwnerWithProposal is IOwnable {\\n address private s_owner;\\n address private s_pendingOwner;\\n\\n event OwnershipTransferRequested(address indexed from, address indexed to);\\n event OwnershipTransferred(address indexed from, address indexed to);\\n\\n constructor(address newOwner, address pendingOwner) {\\n // solhint-disable-next-line gas-custom-errors\\n require(newOwner != address(0), \\\"Cannot set owner to zero\\\");\\n\\n s_owner = newOwner;\\n if (pendingOwner != address(0)) {\\n _transferOwnership(pendingOwner);\\n }\\n }\\n\\n /// @notice Allows an owner to begin transferring ownership to a new address.\\n function transferOwnership(address to) public override onlyOwner {\\n _transferOwnership(to);\\n }\\n\\n /// @notice Allows an ownership transfer to be completed by the recipient.\\n function acceptOwnership() external override {\\n // solhint-disable-next-line gas-custom-errors\\n require(msg.sender == s_pendingOwner, \\\"Must be proposed owner\\\");\\n\\n address oldOwner = s_owner;\\n s_owner = msg.sender;\\n s_pendingOwner = address(0);\\n\\n emit OwnershipTransferred(oldOwner, msg.sender);\\n }\\n\\n /// @notice Get the current owner\\n function owner() public view override returns (address) {\\n return s_owner;\\n }\\n\\n /// @notice validate, transfer ownership, and emit relevant events\\n function _transferOwnership(address to) private {\\n // solhint-disable-next-line gas-custom-errors\\n require(to != msg.sender, \\\"Cannot transfer to self\\\");\\n\\n s_pendingOwner = to;\\n\\n emit OwnershipTransferRequested(s_owner, to);\\n }\\n\\n /// @notice validate access\\n function _validateOwnership() internal view {\\n // solhint-disable-next-line gas-custom-errors\\n require(msg.sender == s_owner, \\\"Only callable by owner\\\");\\n }\\n\\n /// @notice Reverts if called by anyone other than the contract owner.\\n modifier onlyOwner() {\\n _validateOwnership();\\n _;\\n }\\n}\\n\",\"keccak256\":\"0x2422a055657a87e98be61f8f31abb1824ec50fd0f73949f4e3c6ac877efb6da8\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IOwnable {\\n function owner() external returns (address);\\n\\n function transferOwnership(address recipient) external;\\n\\n function acceptOwnership() external;\\n}\\n\",\"keccak256\":\"0x885de72b7b4e4f1bf8ba817a3f2bcc37fd9022d342c4ce76782151c30122d767\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {IVRFCoordinatorV2Plus} from \\\"./interfaces/IVRFCoordinatorV2Plus.sol\\\";\\nimport {IVRFMigratableConsumerV2Plus} from \\\"./interfaces/IVRFMigratableConsumerV2Plus.sol\\\";\\nimport {ConfirmedOwner} from \\\"../../shared/access/ConfirmedOwner.sol\\\";\\n\\n/** ****************************************************************************\\n * @notice Interface for contracts using VRF randomness\\n * *****************************************************************************\\n * @dev PURPOSE\\n *\\n * @dev Reggie the Random Oracle (not his real job) wants to provide randomness\\n * @dev to Vera the verifier in such a way that Vera can be sure he's not\\n * @dev making his output up to suit himself. Reggie provides Vera a public key\\n * @dev to which he knows the secret key. Each time Vera provides a seed to\\n * @dev Reggie, he gives back a value which is computed completely\\n * @dev deterministically from the seed and the secret key.\\n *\\n * @dev Reggie provides a proof by which Vera can verify that the output was\\n * @dev correctly computed once Reggie tells it to her, but without that proof,\\n * @dev the output is indistinguishable to her from a uniform random sample\\n * @dev from the output space.\\n *\\n * @dev The purpose of this contract is to make it easy for unrelated contracts\\n * @dev to talk to Vera the verifier about the work Reggie is doing, to provide\\n * @dev simple access to a verifiable source of randomness. It ensures 2 things:\\n * @dev 1. The fulfillment came from the VRFCoordinatorV2Plus.\\n * @dev 2. The consumer contract implements fulfillRandomWords.\\n * *****************************************************************************\\n * @dev USAGE\\n *\\n * @dev Calling contracts must inherit from VRFConsumerBaseV2Plus, and can\\n * @dev initialize VRFConsumerBaseV2Plus's attributes in their constructor as\\n * @dev shown:\\n *\\n * @dev contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus {\\n * @dev constructor(, address _vrfCoordinator, address _subOwner)\\n * @dev VRFConsumerBaseV2Plus(_vrfCoordinator, _subOwner) public {\\n * @dev \\n * @dev }\\n * @dev }\\n *\\n * @dev The oracle will have given you an ID for the VRF keypair they have\\n * @dev committed to (let's call it keyHash). Create a subscription, fund it\\n * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface\\n * @dev subscription management functions).\\n * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,\\n * @dev callbackGasLimit, numWords, extraArgs),\\n * @dev see (IVRFCoordinatorV2Plus for a description of the arguments).\\n *\\n * @dev Once the VRFCoordinatorV2Plus has received and validated the oracle's response\\n * @dev to your request, it will call your contract's fulfillRandomWords method.\\n *\\n * @dev The randomness argument to fulfillRandomWords is a set of random words\\n * @dev generated from your requestId and the blockHash of the request.\\n *\\n * @dev If your contract could have concurrent requests open, you can use the\\n * @dev requestId returned from requestRandomWords to track which response is associated\\n * @dev with which randomness request.\\n * @dev See \\\"SECURITY CONSIDERATIONS\\\" for principles to keep in mind,\\n * @dev if your contract could have multiple requests in flight simultaneously.\\n *\\n * @dev Colliding `requestId`s are cryptographically impossible as long as seeds\\n * @dev differ.\\n *\\n * *****************************************************************************\\n * @dev SECURITY CONSIDERATIONS\\n *\\n * @dev A method with the ability to call your fulfillRandomness method directly\\n * @dev could spoof a VRF response with any random value, so it's critical that\\n * @dev it cannot be directly called by anything other than this base contract\\n * @dev (specifically, by the VRFConsumerBaseV2Plus.rawFulfillRandomness method).\\n *\\n * @dev For your users to trust that your contract's random behavior is free\\n * @dev from malicious interference, it's best if you can write it so that all\\n * @dev behaviors implied by a VRF response are executed *during* your\\n * @dev fulfillRandomness method. If your contract must store the response (or\\n * @dev anything derived from it) and use it later, you must ensure that any\\n * @dev user-significant behavior which depends on that stored value cannot be\\n * @dev manipulated by a subsequent VRF request.\\n *\\n * @dev Similarly, both miners and the VRF oracle itself have some influence\\n * @dev over the order in which VRF responses appear on the blockchain, so if\\n * @dev your contract could have multiple VRF requests in flight simultaneously,\\n * @dev you must ensure that the order in which the VRF responses arrive cannot\\n * @dev be used to manipulate your contract's user-significant behavior.\\n *\\n * @dev Since the block hash of the block which contains the requestRandomness\\n * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful\\n * @dev miner could, in principle, fork the blockchain to evict the block\\n * @dev containing the request, forcing the request to be included in a\\n * @dev different block with a different hash, and therefore a different input\\n * @dev to the VRF. However, such an attack would incur a substantial economic\\n * @dev cost. This cost scales with the number of blocks the VRF oracle waits\\n * @dev until it calls responds to a request. It is for this reason that\\n * @dev that you can signal to an oracle you'd like them to wait longer before\\n * @dev responding to the request (however this is not enforced in the contract\\n * @dev and so remains effective only in the case of unmodified oracle software).\\n */\\nabstract contract VRFConsumerBaseV2Plus is IVRFMigratableConsumerV2Plus, ConfirmedOwner {\\n error OnlyCoordinatorCanFulfill(address have, address want);\\n error OnlyOwnerOrCoordinator(address have, address owner, address coordinator);\\n error ZeroAddress();\\n\\n // s_vrfCoordinator should be used by consumers to make requests to vrfCoordinator\\n // so that coordinator reference is updated after migration\\n IVRFCoordinatorV2Plus public s_vrfCoordinator;\\n\\n /**\\n * @param _vrfCoordinator address of VRFCoordinator contract\\n */\\n constructor(address _vrfCoordinator) ConfirmedOwner(msg.sender) {\\n if (_vrfCoordinator == address(0)) {\\n revert ZeroAddress();\\n }\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n }\\n\\n /**\\n * @notice fulfillRandomness handles the VRF response. Your contract must\\n * @notice implement it. See \\\"SECURITY CONSIDERATIONS\\\" above for important\\n * @notice principles to keep in mind when implementing your fulfillRandomness\\n * @notice method.\\n *\\n * @dev VRFConsumerBaseV2Plus expects its subcontracts to have a method with this\\n * @dev signature, and will call it once it has verified the proof\\n * @dev associated with the randomness. (It is triggered via a call to\\n * @dev rawFulfillRandomness, below.)\\n *\\n * @param requestId The Id initially returned by requestRandomness\\n * @param randomWords the VRF output expanded to the requested number of words\\n */\\n // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\\n function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal virtual;\\n\\n // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF\\n // proof. rawFulfillRandomness then calls fulfillRandomness, after validating\\n // the origin of the call\\n function rawFulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) external {\\n if (msg.sender != address(s_vrfCoordinator)) {\\n revert OnlyCoordinatorCanFulfill(msg.sender, address(s_vrfCoordinator));\\n }\\n fulfillRandomWords(requestId, randomWords);\\n }\\n\\n /**\\n * @inheritdoc IVRFMigratableConsumerV2Plus\\n */\\n function setCoordinator(address _vrfCoordinator) external override onlyOwnerOrCoordinator {\\n if (_vrfCoordinator == address(0)) {\\n revert ZeroAddress();\\n }\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n\\n emit CoordinatorSet(_vrfCoordinator);\\n }\\n\\n modifier onlyOwnerOrCoordinator() {\\n if (msg.sender != owner() && msg.sender != address(s_vrfCoordinator)) {\\n revert OnlyOwnerOrCoordinator(msg.sender, owner(), address(s_vrfCoordinator));\\n }\\n _;\\n }\\n}\\n\",\"keccak256\":\"0x0c92838396c5abe72754ebeae526a0434dd53fdaf63e6b98111aebd6114cfcc2\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {VRFV2PlusClient} from \\\"../libraries/VRFV2PlusClient.sol\\\";\\nimport {IVRFSubscriptionV2Plus} from \\\"./IVRFSubscriptionV2Plus.sol\\\";\\n\\n// Interface that enables consumers of VRFCoordinatorV2Plus to be future-proof for upgrades\\n// This interface is supported by subsequent versions of VRFCoordinatorV2Plus\\ninterface IVRFCoordinatorV2Plus is IVRFSubscriptionV2Plus {\\n /**\\n * @notice Request a set of random words.\\n * @param req - a struct containing following fields for randomness request:\\n * keyHash - Corresponds to a particular oracle job which uses\\n * that key for generating the VRF proof. Different keyHash's have different gas price\\n * ceilings, so you can select a specific one to bound your maximum per request cost.\\n * subId - The ID of the VRF subscription. Must be funded\\n * with the minimum subscription balance required for the selected keyHash.\\n * requestConfirmations - How many blocks you'd like the\\n * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS\\n * for why you may want to request more. The acceptable range is\\n * [minimumRequestBlockConfirmations, 200].\\n * callbackGasLimit - How much gas you'd like to receive in your\\n * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords\\n * may be slightly less than this amount because of gas used calling the function\\n * (argument decoding etc.), so you may need to request slightly more than you expect\\n * to have inside fulfillRandomWords. The acceptable range is\\n * [0, maxGasLimit]\\n * numWords - The number of uint256 random values you'd like to receive\\n * in your fulfillRandomWords callback. Note these numbers are expanded in a\\n * secure way by the VRFCoordinator from a single random value supplied by the oracle.\\n * extraArgs - abi-encoded extra args\\n * @return requestId - A unique identifier of the request. Can be used to match\\n * a request to a response in fulfillRandomWords.\\n */\\n function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId);\\n}\\n\",\"keccak256\":\"0x7dca2a64690ddd95ee05e422e1f61e7c1d701aaf5be1390ae12e9bd144266c36\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice The IVRFMigratableConsumerV2Plus interface defines the\\n/// @notice method required to be implemented by all V2Plus consumers.\\n/// @dev This interface is designed to be used in VRFConsumerBaseV2Plus.\\ninterface IVRFMigratableConsumerV2Plus {\\n event CoordinatorSet(address vrfCoordinator);\\n\\n /// @notice Sets the VRF Coordinator address\\n /// @notice This method should only be callable by the coordinator or contract owner\\n function setCoordinator(address vrfCoordinator) external;\\n}\\n\",\"keccak256\":\"0x8be8744e3b8380dc85354cf110e8caef8f394266e79120ad675a7da835ed2a85\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice The IVRFSubscriptionV2Plus interface defines the subscription\\n/// @notice related methods implemented by the V2Plus coordinator.\\ninterface IVRFSubscriptionV2Plus {\\n /**\\n * @notice Add a consumer to a VRF subscription.\\n * @param subId - ID of the subscription\\n * @param consumer - New consumer which can use the subscription\\n */\\n function addConsumer(uint256 subId, address consumer) external;\\n\\n /**\\n * @notice Remove a consumer from a VRF subscription.\\n * @param subId - ID of the subscription\\n * @param consumer - Consumer to remove from the subscription\\n */\\n function removeConsumer(uint256 subId, address consumer) external;\\n\\n /**\\n * @notice Cancel a subscription\\n * @param subId - ID of the subscription\\n * @param to - Where to send the remaining LINK to\\n */\\n function cancelSubscription(uint256 subId, address to) external;\\n\\n /**\\n * @notice Accept subscription owner transfer.\\n * @param subId - ID of the subscription\\n * @dev will revert if original owner of subId has\\n * not requested that msg.sender become the new owner.\\n */\\n function acceptSubscriptionOwnerTransfer(uint256 subId) external;\\n\\n /**\\n * @notice Request subscription owner transfer.\\n * @param subId - ID of the subscription\\n * @param newOwner - proposed new owner of the subscription\\n */\\n function requestSubscriptionOwnerTransfer(uint256 subId, address newOwner) external;\\n\\n /**\\n * @notice Create a VRF subscription.\\n * @return subId - A unique subscription id.\\n * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.\\n * @dev Note to fund the subscription with LINK, use transferAndCall. For example\\n * @dev LINKTOKEN.transferAndCall(\\n * @dev address(COORDINATOR),\\n * @dev amount,\\n * @dev abi.encode(subId));\\n * @dev Note to fund the subscription with Native, use fundSubscriptionWithNative. Be sure\\n * @dev to send Native with the call, for example:\\n * @dev COORDINATOR.fundSubscriptionWithNative{value: amount}(subId);\\n */\\n function createSubscription() external returns (uint256 subId);\\n\\n /**\\n * @notice Get a VRF subscription.\\n * @param subId - ID of the subscription\\n * @return balance - LINK balance of the subscription in juels.\\n * @return nativeBalance - native balance of the subscription in wei.\\n * @return reqCount - Requests count of subscription.\\n * @return owner - owner of the subscription.\\n * @return consumers - list of consumer address which are able to use this subscription.\\n */\\n function getSubscription(\\n uint256 subId\\n )\\n external\\n view\\n returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers);\\n\\n /*\\n * @notice Check to see if there exists a request commitment consumers\\n * for all consumers and keyhashes for a given sub.\\n * @param subId - ID of the subscription\\n * @return true if there exists at least one unfulfilled request for the subscription, false\\n * otherwise.\\n */\\n function pendingRequestExists(uint256 subId) external view returns (bool);\\n\\n /**\\n * @notice Paginate through all active VRF subscriptions.\\n * @param startIndex index of the subscription to start from\\n * @param maxCount maximum number of subscriptions to return, 0 to return all\\n * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one\\n * @dev should consider keeping the blockheight constant to ensure a holistic picture of the contract state\\n */\\n function getActiveSubscriptionIds(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory);\\n\\n /**\\n * @notice Fund a subscription with native.\\n * @param subId - ID of the subscription\\n * @notice This method expects msg.value to be greater than or equal to 0.\\n */\\n function fundSubscriptionWithNative(uint256 subId) external payable;\\n}\\n\",\"keccak256\":\"0x85b348297ce36794e3bf97a47c001fc216bd0ee243e91514a7b395f3fcd189b0\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n// End consumer library.\\nlibrary VRFV2PlusClient {\\n // extraArgs will evolve to support new features\\n bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256(\\\"VRF ExtraArgsV1\\\"));\\n struct ExtraArgsV1 {\\n bool nativePayment;\\n }\\n\\n struct RandomWordsRequest {\\n bytes32 keyHash;\\n uint256 subId;\\n uint16 requestConfirmations;\\n uint32 callbackGasLimit;\\n uint32 numWords;\\n bytes extraArgs;\\n }\\n\\n function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {\\n return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs);\\n }\\n}\\n\",\"keccak256\":\"0x839ad7a737ef18147b518b4ec3cbaf4a49dc994db65cf8369ed4e69d169a98a6\",\"license\":\"MIT\"},\"src/rng/ChainlinkRNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport {VRFConsumerBaseV2Plus, IVRFCoordinatorV2Plus} from \\\"@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol\\\";\\nimport {VRFV2PlusClient} from \\\"@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol\\\";\\n\\nimport \\\"./RNG.sol\\\";\\n\\n/// @title Random Number Generator that uses Chainlink VRF v2.5\\n/// https://blog.chain.link/introducing-vrf-v2-5/\\ncontract ChainlinkRNG is RNG, VRFConsumerBaseV2Plus {\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n address public governor; // The address that can withdraw funds.\\n address public sortitionModule; // The address of the SortitionModule.\\n bytes32 public keyHash; // The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\\n uint256 public subscriptionId; // The unique identifier of the subscription used for funding requests.\\n uint16 public requestConfirmations; // How many confirmations the Chainlink node should wait before responding.\\n // 22 bytes remaining in slot\\n uint32 public callbackGasLimit; // Gas limit for the Chainlink callback.\\n uint256 public lastRequestId; // The last request ID.\\n mapping(uint256 requestId => uint256 number) public randomNumbers; // randomNumbers[requestID] is the random number for this request id, 0 otherwise.\\n\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev Emitted when a request is sent to the VRF Coordinator\\n /// @param requestId The ID of the request\\n event RequestSent(uint256 indexed requestId);\\n\\n /// Emitted when a request has been fulfilled.\\n /// @param requestId The ID of the request\\n /// @param randomWord The random value answering the request.\\n event RequestFulfilled(uint256 indexed requestId, uint256 randomWord);\\n\\n // ************************************* //\\n // * Function Modifiers * //\\n // ************************************* //\\n\\n modifier onlyByGovernor() {\\n require(governor == msg.sender, \\\"Governor only\\\");\\n _;\\n }\\n\\n modifier onlyBySortitionModule() {\\n require(sortitionModule == msg.sender, \\\"SortitionModule only\\\");\\n _;\\n }\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor, initializing the implementation to reduce attack surface.\\n /// @param _governor The Governor of the contract.\\n /// @param _sortitionModule The address of the SortitionModule contract.\\n /// @param _vrfCoordinator The address of the VRFCoordinator contract.\\n /// @param _keyHash The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\\n /// @param _subscriptionId The unique identifier of the subscription used for funding requests.\\n /// @param _requestConfirmations How many confirmations the Chainlink node should wait before responding.\\n /// @param _callbackGasLimit The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.\\n /// @dev https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number\\n constructor(\\n address _governor,\\n address _sortitionModule,\\n address _vrfCoordinator,\\n bytes32 _keyHash,\\n uint256 _subscriptionId,\\n uint16 _requestConfirmations,\\n uint32 _callbackGasLimit\\n ) VRFConsumerBaseV2Plus(_vrfCoordinator) {\\n governor = _governor;\\n sortitionModule = _sortitionModule;\\n keyHash = _keyHash;\\n subscriptionId = _subscriptionId;\\n requestConfirmations = _requestConfirmations;\\n callbackGasLimit = _callbackGasLimit;\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n /// @dev Changes the governor of the contract.\\n /// @param _governor The new governor.\\n function changeGovernor(address _governor) external onlyByGovernor {\\n governor = _governor;\\n }\\n\\n /// @dev Changes the sortition module of the contract.\\n /// @param _sortitionModule The new sortition module.\\n function changeSortitionModule(address _sortitionModule) external onlyByGovernor {\\n sortitionModule = _sortitionModule;\\n }\\n\\n /// @dev Changes the VRF Coordinator of the contract.\\n /// @param _vrfCoordinator The new VRF Coordinator.\\n function changeVrfCoordinator(address _vrfCoordinator) external onlyByGovernor {\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n emit CoordinatorSet(_vrfCoordinator);\\n }\\n\\n /// @dev Changes the key hash of the contract.\\n /// @param _keyHash The new key hash.\\n function changeKeyHash(bytes32 _keyHash) external onlyByGovernor {\\n keyHash = _keyHash;\\n }\\n\\n /// @dev Changes the subscription ID of the contract.\\n /// @param _subscriptionId The new subscription ID.\\n function changeSubscriptionId(uint256 _subscriptionId) external onlyByGovernor {\\n subscriptionId = _subscriptionId;\\n }\\n\\n /// @dev Changes the request confirmations of the contract.\\n /// @param _requestConfirmations The new request confirmations.\\n function changeRequestConfirmations(uint16 _requestConfirmations) external onlyByGovernor {\\n requestConfirmations = _requestConfirmations;\\n }\\n\\n /// @dev Changes the callback gas limit of the contract.\\n /// @param _callbackGasLimit The new callback gas limit.\\n function changeCallbackGasLimit(uint32 _callbackGasLimit) external onlyByGovernor {\\n callbackGasLimit = _callbackGasLimit;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Request a random number. SortitionModule only.\\n function requestRandomness(uint256 /*_block*/) external override onlyBySortitionModule {\\n // Will revert if subscription is not set and funded.\\n uint256 requestId = s_vrfCoordinator.requestRandomWords(\\n VRFV2PlusClient.RandomWordsRequest({\\n keyHash: keyHash,\\n subId: subscriptionId,\\n requestConfirmations: requestConfirmations,\\n callbackGasLimit: callbackGasLimit,\\n numWords: 1,\\n extraArgs: VRFV2PlusClient._argsToBytes(\\n // Set nativePayment to true to pay for VRF requests with ETH instead of LINK\\n VRFV2PlusClient.ExtraArgsV1({nativePayment: true})\\n )\\n })\\n );\\n lastRequestId = requestId;\\n emit RequestSent(requestId);\\n }\\n\\n /// @dev Callback function called by the VRF Coordinator when the random value is generated.\\n /// @param _requestId The ID of the request.\\n /// @param _randomWords The random values answering the request.\\n function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) internal override {\\n // Access control is handled by the parent VRFCoordinator.rawFulfillRandomWords()\\n randomNumbers[_requestId] = _randomWords[0];\\n emit RequestFulfilled(_requestId, _randomWords[0]);\\n }\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @dev Return the random number.\\n /// @return randomNumber The random number or 0 if it is not ready or has not been requested.\\n function receiveRandomness(uint256 /*_block*/) external view override returns (uint256 randomNumber) {\\n randomNumber = randomNumbers[lastRequestId];\\n }\\n}\\n\",\"keccak256\":\"0xf132cbbbbb47a4f11c248fab30212a3dd3e7b20b1bc5b543ff21b6d291367dc8\",\"license\":\"MIT\"},\"src/rng/RNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\ninterface RNG {\\n /// @dev Request a random number.\\n /// @param _block Block linked to the request.\\n function requestRandomness(uint256 _block) external;\\n\\n /// @dev Receive the random number.\\n /// @param _block Block the random number is linked to.\\n /// @return randomNumber Random Number. If the number is not ready or has not been required 0 instead.\\n function receiveRandomness(uint256 _block) external returns (uint256 randomNumber);\\n}\\n\",\"keccak256\":\"0xf92e0cf768afefc5cc6ef786c263b67dd00c021aa5753213dbbc33014adb68c5\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162000f6038038062000f6083398101604081905262000034916200022d565b8433806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000165565b5050506001600160a01b038116620000ea5760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b03199081166001600160a01b03938416179091556003805482169983169990991790985560048054909816961695909517909555600591909155600655506007805461ffff90931665ffffffffffff19909316929092176201000063ffffffff90921691909102179055620002c5565b336001600160a01b03821603620001bf5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200022857600080fd5b919050565b600080600080600080600060e0888a0312156200024957600080fd5b620002548862000210565b9650620002646020890162000210565b9550620002746040890162000210565b9450606088015193506080880151925060a088015161ffff811681146200029a57600080fd5b60c089015190925063ffffffff81168114620002b557600080fd5b8091505092959891949750929550565b610c8b80620002d56000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c806379ba5097116100c3578063e4c0aaf41161007c578063e4c0aaf4146102e5578063e86a51cb146102f8578063f2fde38b1461030b578063f50d390d1461031e578063f9f5dd9114610331578063fc2a88c31461034457600080fd5b806379ba5097146102725780638da5cb5b1461027a5780638ea981171461028b5780639eccacf61461029e578063b0049637146102b1578063b0fb162f146102c457600080fd5b80632e1daf2f116101155780632e1daf2f146101fd5780632f68f4821461021057806339b1e245146102235780635257cd901461023657806361728f39146102565780637363ae1f1461025f57600080fd5b806309c1ba2e146101525780630c340a241461016e57806313cf9054146101995780631fe543e3146101bd57806324f74697146101d2575b600080fd5b61015b60065481565b6040519081526020015b60405180910390f35b600354610181906001600160a01b031681565b6040516001600160a01b039091168152602001610165565b61015b6101a7366004610a4f565b5060085460009081526009602052604090205490565b6101d06101cb366004610a68565b61034d565b005b6007546101e89062010000900463ffffffff1681565b60405163ffffffff9091168152602001610165565b600454610181906001600160a01b031681565b6101d061021e366004610a4f565b6103a2565b6101d0610231366004610a4f565b6103d1565b61015b610244366004610a4f565b60096020526000908152604090205481565b61015b60055481565b6101d061026d366004610a4f565b610400565b6101d061055b565b6000546001600160a01b0316610181565b6101d0610299366004610ae7565b610605565b600254610181906001600160a01b031681565b6101d06102bf366004610ae7565b6106f7565b6007546102d29061ffff1681565b60405161ffff9091168152602001610165565b6101d06102f3366004610ae7565b610743565b6101d0610306366004610b17565b61078f565b6101d0610319366004610ae7565b6107dd565b6101d061032c366004610b3d565b6107f1565b6101d061033f366004610ae7565b610833565b61015b60085481565b6002546001600160a01b031633146103925760025460405163073e64fd60e21b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b61039d83838361085d565b505050565b6003546001600160a01b031633146103cc5760405162461bcd60e51b815260040161038990610b61565b600555565b6003546001600160a01b031633146103fb5760405162461bcd60e51b815260040161038990610b61565b600655565b6004546001600160a01b031633146104515760405162461bcd60e51b8152602060048201526014602482015273536f72746974696f6e4d6f64756c65206f6e6c7960601b6044820152606401610389565b6002546040805160c081018252600554815260065460208083019190915260075461ffff81168385015262010000900463ffffffff16606083015260016080830181905283519182019093529182526000926001600160a01b031691639b1c385e919060a08201906104c2906108e6565b8152506040518263ffffffff1660e01b81526004016104e19190610b88565b6020604051808303816000875af1158015610500573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105249190610c26565b600881905560405190915081907f0cd21a41891ff04ecd9a8754bec97e2fb85d2a4e7694329d4dc364c796f23d0690600090a25050565b6001546001600160a01b031633146105ae5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610389565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331480159061062b57506002546001600160a01b03163314155b1561067c57336106436000546001600160a01b031690565b60025460405163061db9c160e01b81526001600160a01b0393841660048201529183166024830152919091166044820152606401610389565b6001600160a01b0381166106a35760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be69060200160405180910390a150565b6003546001600160a01b031633146107215760405162461bcd60e51b815260040161038990610b61565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b0316331461076d5760405162461bcd60e51b815260040161038990610b61565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107b95760405162461bcd60e51b815260040161038990610b61565b6007805463ffffffff909216620100000265ffffffff000019909216919091179055565b6107e5610957565b6107ee816109ac565b50565b6003546001600160a01b0316331461081b5760405162461bcd60e51b815260040161038990610b61565b6007805461ffff191661ffff92909216919091179055565b6003546001600160a01b031633146106a35760405162461bcd60e51b815260040161038990610b61565b8181600081811061087057610870610c3f565b905060200201356009600085815260200190815260200160002081905550827f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d5838360008181106108c3576108c3610c3f565b905060200201356040516108d991815260200190565b60405180910390a2505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161091f91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000546001600160a01b031633146109aa5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610389565b565b336001600160a01b038216036109fe5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610389565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a6157600080fd5b5035919050565b600080600060408486031215610a7d57600080fd5b83359250602084013567ffffffffffffffff80821115610a9c57600080fd5b818601915086601f830112610ab057600080fd5b813581811115610abf57600080fd5b8760208260051b8501011115610ad457600080fd5b6020830194508093505050509250925092565b600060208284031215610af957600080fd5b81356001600160a01b0381168114610b1057600080fd5b9392505050565b600060208284031215610b2957600080fd5b813563ffffffff81168114610b1057600080fd5b600060208284031215610b4f57600080fd5b813561ffff81168114610b1057600080fd5b6020808252600d908201526c476f7665726e6f72206f6e6c7960981b604082015260600190565b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015610c015782810184015186820161010001528301610be4565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610c3857600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fdfea26469706673582212201c20e67178fd79424f46cb830b3496516dfa70ea88c1d07b59de6b70b0f17ca764736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061014d5760003560e01c806379ba5097116100c3578063e4c0aaf41161007c578063e4c0aaf4146102e5578063e86a51cb146102f8578063f2fde38b1461030b578063f50d390d1461031e578063f9f5dd9114610331578063fc2a88c31461034457600080fd5b806379ba5097146102725780638da5cb5b1461027a5780638ea981171461028b5780639eccacf61461029e578063b0049637146102b1578063b0fb162f146102c457600080fd5b80632e1daf2f116101155780632e1daf2f146101fd5780632f68f4821461021057806339b1e245146102235780635257cd901461023657806361728f39146102565780637363ae1f1461025f57600080fd5b806309c1ba2e146101525780630c340a241461016e57806313cf9054146101995780631fe543e3146101bd57806324f74697146101d2575b600080fd5b61015b60065481565b6040519081526020015b60405180910390f35b600354610181906001600160a01b031681565b6040516001600160a01b039091168152602001610165565b61015b6101a7366004610a4f565b5060085460009081526009602052604090205490565b6101d06101cb366004610a68565b61034d565b005b6007546101e89062010000900463ffffffff1681565b60405163ffffffff9091168152602001610165565b600454610181906001600160a01b031681565b6101d061021e366004610a4f565b6103a2565b6101d0610231366004610a4f565b6103d1565b61015b610244366004610a4f565b60096020526000908152604090205481565b61015b60055481565b6101d061026d366004610a4f565b610400565b6101d061055b565b6000546001600160a01b0316610181565b6101d0610299366004610ae7565b610605565b600254610181906001600160a01b031681565b6101d06102bf366004610ae7565b6106f7565b6007546102d29061ffff1681565b60405161ffff9091168152602001610165565b6101d06102f3366004610ae7565b610743565b6101d0610306366004610b17565b61078f565b6101d0610319366004610ae7565b6107dd565b6101d061032c366004610b3d565b6107f1565b6101d061033f366004610ae7565b610833565b61015b60085481565b6002546001600160a01b031633146103925760025460405163073e64fd60e21b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b61039d83838361085d565b505050565b6003546001600160a01b031633146103cc5760405162461bcd60e51b815260040161038990610b61565b600555565b6003546001600160a01b031633146103fb5760405162461bcd60e51b815260040161038990610b61565b600655565b6004546001600160a01b031633146104515760405162461bcd60e51b8152602060048201526014602482015273536f72746974696f6e4d6f64756c65206f6e6c7960601b6044820152606401610389565b6002546040805160c081018252600554815260065460208083019190915260075461ffff81168385015262010000900463ffffffff16606083015260016080830181905283519182019093529182526000926001600160a01b031691639b1c385e919060a08201906104c2906108e6565b8152506040518263ffffffff1660e01b81526004016104e19190610b88565b6020604051808303816000875af1158015610500573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105249190610c26565b600881905560405190915081907f0cd21a41891ff04ecd9a8754bec97e2fb85d2a4e7694329d4dc364c796f23d0690600090a25050565b6001546001600160a01b031633146105ae5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610389565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331480159061062b57506002546001600160a01b03163314155b1561067c57336106436000546001600160a01b031690565b60025460405163061db9c160e01b81526001600160a01b0393841660048201529183166024830152919091166044820152606401610389565b6001600160a01b0381166106a35760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be69060200160405180910390a150565b6003546001600160a01b031633146107215760405162461bcd60e51b815260040161038990610b61565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b0316331461076d5760405162461bcd60e51b815260040161038990610b61565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107b95760405162461bcd60e51b815260040161038990610b61565b6007805463ffffffff909216620100000265ffffffff000019909216919091179055565b6107e5610957565b6107ee816109ac565b50565b6003546001600160a01b0316331461081b5760405162461bcd60e51b815260040161038990610b61565b6007805461ffff191661ffff92909216919091179055565b6003546001600160a01b031633146106a35760405162461bcd60e51b815260040161038990610b61565b8181600081811061087057610870610c3f565b905060200201356009600085815260200190815260200160002081905550827f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d5838360008181106108c3576108c3610c3f565b905060200201356040516108d991815260200190565b60405180910390a2505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161091f91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000546001600160a01b031633146109aa5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610389565b565b336001600160a01b038216036109fe5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610389565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a6157600080fd5b5035919050565b600080600060408486031215610a7d57600080fd5b83359250602084013567ffffffffffffffff80821115610a9c57600080fd5b818601915086601f830112610ab057600080fd5b813581811115610abf57600080fd5b8760208260051b8501011115610ad457600080fd5b6020830194508093505050509250925092565b600060208284031215610af957600080fd5b81356001600160a01b0381168114610b1057600080fd5b9392505050565b600060208284031215610b2957600080fd5b813563ffffffff81168114610b1057600080fd5b600060208284031215610b4f57600080fd5b813561ffff81168114610b1057600080fd5b6020808252600d908201526c476f7665726e6f72206f6e6c7960981b604082015260600190565b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015610c015782810184015186820161010001528301610be4565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610c3857600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fdfea26469706673582212201c20e67178fd79424f46cb830b3496516dfa70ea88c1d07b59de6b70b0f17ca764736f6c63430008180033", + "devdoc": { + "events": { + "RequestFulfilled(uint256,uint256)": { + "params": { + "randomWord": "The random value answering the request.", + "requestId": "The ID of the request" + } + }, + "RequestSent(uint256)": { + "details": "Emitted when a request is sent to the VRF Coordinator", + "params": { + "requestId": "The ID of the request" + } + } + }, + "kind": "dev", + "methods": { + "changeCallbackGasLimit(uint32)": { + "details": "Changes the callback gas limit of the contract.", + "params": { + "_callbackGasLimit": "The new callback gas limit." + } + }, + "changeGovernor(address)": { + "details": "Changes the governor of the contract.", + "params": { + "_governor": "The new governor." + } + }, + "changeKeyHash(bytes32)": { + "details": "Changes the key hash of the contract.", + "params": { + "_keyHash": "The new key hash." + } + }, + "changeRequestConfirmations(uint16)": { + "details": "Changes the request confirmations of the contract.", + "params": { + "_requestConfirmations": "The new request confirmations." + } + }, + "changeSortitionModule(address)": { + "details": "Changes the sortition module of the contract.", + "params": { + "_sortitionModule": "The new sortition module." + } + }, + "changeSubscriptionId(uint256)": { + "details": "Changes the subscription ID of the contract.", + "params": { + "_subscriptionId": "The new subscription ID." + } + }, + "changeVrfCoordinator(address)": { + "details": "Changes the VRF Coordinator of the contract.", + "params": { + "_vrfCoordinator": "The new VRF Coordinator." + } + }, + "constructor": { + "details": "Constructor, initializing the implementation to reduce attack surface.https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number", + "params": { + "_callbackGasLimit": "The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.", + "_governor": "The Governor of the contract.", + "_keyHash": "The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).", + "_requestConfirmations": "How many confirmations the Chainlink node should wait before responding.", + "_sortitionModule": "The address of the SortitionModule contract.", + "_subscriptionId": "The unique identifier of the subscription used for funding requests.", + "_vrfCoordinator": "The address of the VRFCoordinator contract." + } + }, + "receiveRandomness(uint256)": { + "details": "Return the random number.", + "returns": { + "randomNumber": "The random number or 0 if it is not ready or has not been requested." + } + }, + "requestRandomness(uint256)": { + "details": "Request a random number. SortitionModule only." + } + }, + "title": "Random Number Generator that uses Chainlink VRF v2.5 https://blog.chain.link/introducing-vrf-v2-5/", + "version": 1 + }, + "userdoc": { + "events": { + "RequestFulfilled(uint256,uint256)": { + "notice": "Emitted when a request has been fulfilled." + } + }, + "kind": "user", + "methods": { + "acceptOwnership()": { + "notice": "Allows an ownership transfer to be completed by the recipient." + }, + "owner()": { + "notice": "Get the current owner" + }, + "setCoordinator(address)": { + "notice": "Sets the VRF Coordinator addressThis method should only be callable by the coordinator or contract owner" + }, + "transferOwnership(address)": { + "notice": "Allows an owner to begin transferring ownership to a new address." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 29, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "s_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 31, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "s_pendingOwner", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 231, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "s_vrfCoordinator", + "offset": 0, + "slot": "2", + "type": "t_contract(IVRFCoordinatorV2Plus)380" + }, + { + "astId": 35404, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "governor", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 35406, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "sortitionModule", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 35408, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "keyHash", + "offset": 0, + "slot": "5", + "type": "t_bytes32" + }, + { + "astId": 35410, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "subscriptionId", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 35412, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "requestConfirmations", + "offset": 0, + "slot": "7", + "type": "t_uint16" + }, + { + "astId": 35414, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "callbackGasLimit", + "offset": 2, + "slot": "7", + "type": "t_uint32" + }, + { + "astId": 35416, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "lastRequestId", + "offset": 0, + "slot": "8", + "type": "t_uint256" + }, + { + "astId": 35420, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "randomNumbers", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_uint256,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IVRFCoordinatorV2Plus)380": { + "encoding": "inplace", + "label": "contract IVRFCoordinatorV2Plus", + "numberOfBytes": "20" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint16": { + "encoding": "inplace", + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + } + } + } +} diff --git a/contracts/deployments/arbitrumSepolia/ChainlinkRNG.json b/contracts/deployments/arbitrumSepolia/ChainlinkRNG.json new file mode 100644 index 000000000..d0d5dd139 --- /dev/null +++ b/contracts/deployments/arbitrumSepolia/ChainlinkRNG.json @@ -0,0 +1,749 @@ +{ + "address": "0xAd5cCc93429e3A977c273cEeD106Ef16A69EAf79", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + }, + { + "internalType": "address", + "name": "_sortitionModule", + "type": "address" + }, + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_subscriptionId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "randomWord", + "type": "uint256" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "callbackGasLimit", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + } + ], + "name": "changeCallbackGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "changeGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + } + ], + "name": "changeKeyHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + } + ], + "name": "changeRequestConfirmations", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_sortitionModule", + "type": "address" + } + ], + "name": "changeSortitionModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_subscriptionId", + "type": "uint256" + } + ], + "name": "changeSubscriptionId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "changeVrfCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "randomNumbers", + "outputs": [ + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "receiveRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "randomNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "requestConfirmations", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "requestRandomness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sortitionModule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subscriptionId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x40a4e8c98cb08f8cbfb734bbe1fdb551035cb3bce73044eba88b8bc2723ed44c", + "receipt": { + "to": null, + "from": "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "contractAddress": "0xAd5cCc93429e3A977c273cEeD106Ef16A69EAf79", + "transactionIndex": 3, + "gasUsed": "1670556", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xcb374d845b9e5586106b1ae48e46d1e3cd94a0e059a21decb57ff5c08ba982d3", + "transactionHash": "0x40a4e8c98cb08f8cbfb734bbe1fdb551035cb3bce73044eba88b8bc2723ed44c", + "logs": [], + "blockNumber": 105821815, + "cumulativeGasUsed": "2209341", + "status": 1, + "byzantium": true + }, + "args": [ + "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "0x5CE8D5A2BC84beb22a398CCA51996F7930313D61", + "0x1770bdc7eec7771f7ba4ffd640f34260d7f095b79c92d34a5b2551d6f6cfd2be", + "38502597312983100069991953687934627561654236680431968938019951490339399569548", + 200, + 100000 + ], + "numDeployments": 1, + "solcInputHash": "409820253ec776b564318c3061b7e926", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_sortitionModule\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_subscriptionId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"want\",\"type\":\"address\"}],\"name\":\"OnlyCoordinatorCanFulfill\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"OnlyOwnerOrCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vrfCoordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"randomWord\",\"type\":\"uint256\"}],\"name\":\"RequestFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"RequestSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"callbackGasLimit\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"name\":\"changeCallbackGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"}],\"name\":\"changeKeyHash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"}],\"name\":\"changeRequestConfirmations\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sortitionModule\",\"type\":\"address\"}],\"name\":\"changeSortitionModule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_subscriptionId\",\"type\":\"uint256\"}],\"name\":\"changeSubscriptionId\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"changeVrfCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"keyHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastRequestId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"randomNumbers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"receiveRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"randomNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requestConfirmations\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"requestRandomness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_vrfCoordinator\",\"outputs\":[{\"internalType\":\"contract IVRFCoordinatorV2Plus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sortitionModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"subscriptionId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"RequestFulfilled(uint256,uint256)\":{\"params\":{\"randomWord\":\"The random value answering the request.\",\"requestId\":\"The ID of the request\"}},\"RequestSent(uint256)\":{\"details\":\"Emitted when a request is sent to the VRF Coordinator\",\"params\":{\"requestId\":\"The ID of the request\"}}},\"kind\":\"dev\",\"methods\":{\"changeCallbackGasLimit(uint32)\":{\"details\":\"Changes the callback gas limit of the contract.\",\"params\":{\"_callbackGasLimit\":\"The new callback gas limit.\"}},\"changeGovernor(address)\":{\"details\":\"Changes the governor of the contract.\",\"params\":{\"_governor\":\"The new governor.\"}},\"changeKeyHash(bytes32)\":{\"details\":\"Changes the key hash of the contract.\",\"params\":{\"_keyHash\":\"The new key hash.\"}},\"changeRequestConfirmations(uint16)\":{\"details\":\"Changes the request confirmations of the contract.\",\"params\":{\"_requestConfirmations\":\"The new request confirmations.\"}},\"changeSortitionModule(address)\":{\"details\":\"Changes the sortition module of the contract.\",\"params\":{\"_sortitionModule\":\"The new sortition module.\"}},\"changeSubscriptionId(uint256)\":{\"details\":\"Changes the subscription ID of the contract.\",\"params\":{\"_subscriptionId\":\"The new subscription ID.\"}},\"changeVrfCoordinator(address)\":{\"details\":\"Changes the VRF Coordinator of the contract.\",\"params\":{\"_vrfCoordinator\":\"The new VRF Coordinator.\"}},\"constructor\":{\"details\":\"Constructor, initializing the implementation to reduce attack surface.https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number\",\"params\":{\"_callbackGasLimit\":\"The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.\",\"_governor\":\"The Governor of the contract.\",\"_keyHash\":\"The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\",\"_requestConfirmations\":\"How many confirmations the Chainlink node should wait before responding.\",\"_sortitionModule\":\"The address of the SortitionModule contract.\",\"_subscriptionId\":\"The unique identifier of the subscription used for funding requests.\",\"_vrfCoordinator\":\"The address of the VRFCoordinator contract.\"}},\"receiveRandomness(uint256)\":{\"details\":\"Return the random number.\",\"returns\":{\"randomNumber\":\"The random number or 0 if it is not ready or has not been requested.\"}},\"requestRandomness(uint256)\":{\"details\":\"Request a random number. SortitionModule only.\"}},\"title\":\"Random Number Generator that uses Chainlink VRF v2.5 https://blog.chain.link/introducing-vrf-v2-5/\",\"version\":1},\"userdoc\":{\"events\":{\"RequestFulfilled(uint256,uint256)\":{\"notice\":\"Emitted when a request has been fulfilled.\"}},\"kind\":\"user\",\"methods\":{\"acceptOwnership()\":{\"notice\":\"Allows an ownership transfer to be completed by the recipient.\"},\"owner()\":{\"notice\":\"Get the current owner\"},\"setCoordinator(address)\":{\"notice\":\"Sets the VRF Coordinator addressThis method should only be callable by the coordinator or contract owner\"},\"transferOwnership(address)\":{\"notice\":\"Allows an owner to begin transferring ownership to a new address.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/rng/ChainlinkRNG.sol\":\"ChainlinkRNG\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {ConfirmedOwnerWithProposal} from \\\"./ConfirmedOwnerWithProposal.sol\\\";\\n\\n/// @title The ConfirmedOwner contract\\n/// @notice A contract with helpers for basic contract ownership.\\ncontract ConfirmedOwner is ConfirmedOwnerWithProposal {\\n constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}\\n}\\n\",\"keccak256\":\"0xdcb0e9135ddbe71ee27ba99fa06656960c66c964cf2ecb29696da1c1427d9861\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {IOwnable} from \\\"../interfaces/IOwnable.sol\\\";\\n\\n/// @title The ConfirmedOwner contract\\n/// @notice A contract with helpers for basic contract ownership.\\ncontract ConfirmedOwnerWithProposal is IOwnable {\\n address private s_owner;\\n address private s_pendingOwner;\\n\\n event OwnershipTransferRequested(address indexed from, address indexed to);\\n event OwnershipTransferred(address indexed from, address indexed to);\\n\\n constructor(address newOwner, address pendingOwner) {\\n // solhint-disable-next-line gas-custom-errors\\n require(newOwner != address(0), \\\"Cannot set owner to zero\\\");\\n\\n s_owner = newOwner;\\n if (pendingOwner != address(0)) {\\n _transferOwnership(pendingOwner);\\n }\\n }\\n\\n /// @notice Allows an owner to begin transferring ownership to a new address.\\n function transferOwnership(address to) public override onlyOwner {\\n _transferOwnership(to);\\n }\\n\\n /// @notice Allows an ownership transfer to be completed by the recipient.\\n function acceptOwnership() external override {\\n // solhint-disable-next-line gas-custom-errors\\n require(msg.sender == s_pendingOwner, \\\"Must be proposed owner\\\");\\n\\n address oldOwner = s_owner;\\n s_owner = msg.sender;\\n s_pendingOwner = address(0);\\n\\n emit OwnershipTransferred(oldOwner, msg.sender);\\n }\\n\\n /// @notice Get the current owner\\n function owner() public view override returns (address) {\\n return s_owner;\\n }\\n\\n /// @notice validate, transfer ownership, and emit relevant events\\n function _transferOwnership(address to) private {\\n // solhint-disable-next-line gas-custom-errors\\n require(to != msg.sender, \\\"Cannot transfer to self\\\");\\n\\n s_pendingOwner = to;\\n\\n emit OwnershipTransferRequested(s_owner, to);\\n }\\n\\n /// @notice validate access\\n function _validateOwnership() internal view {\\n // solhint-disable-next-line gas-custom-errors\\n require(msg.sender == s_owner, \\\"Only callable by owner\\\");\\n }\\n\\n /// @notice Reverts if called by anyone other than the contract owner.\\n modifier onlyOwner() {\\n _validateOwnership();\\n _;\\n }\\n}\\n\",\"keccak256\":\"0x2422a055657a87e98be61f8f31abb1824ec50fd0f73949f4e3c6ac877efb6da8\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IOwnable {\\n function owner() external returns (address);\\n\\n function transferOwnership(address recipient) external;\\n\\n function acceptOwnership() external;\\n}\\n\",\"keccak256\":\"0x885de72b7b4e4f1bf8ba817a3f2bcc37fd9022d342c4ce76782151c30122d767\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {IVRFCoordinatorV2Plus} from \\\"./interfaces/IVRFCoordinatorV2Plus.sol\\\";\\nimport {IVRFMigratableConsumerV2Plus} from \\\"./interfaces/IVRFMigratableConsumerV2Plus.sol\\\";\\nimport {ConfirmedOwner} from \\\"../../shared/access/ConfirmedOwner.sol\\\";\\n\\n/** ****************************************************************************\\n * @notice Interface for contracts using VRF randomness\\n * *****************************************************************************\\n * @dev PURPOSE\\n *\\n * @dev Reggie the Random Oracle (not his real job) wants to provide randomness\\n * @dev to Vera the verifier in such a way that Vera can be sure he's not\\n * @dev making his output up to suit himself. Reggie provides Vera a public key\\n * @dev to which he knows the secret key. Each time Vera provides a seed to\\n * @dev Reggie, he gives back a value which is computed completely\\n * @dev deterministically from the seed and the secret key.\\n *\\n * @dev Reggie provides a proof by which Vera can verify that the output was\\n * @dev correctly computed once Reggie tells it to her, but without that proof,\\n * @dev the output is indistinguishable to her from a uniform random sample\\n * @dev from the output space.\\n *\\n * @dev The purpose of this contract is to make it easy for unrelated contracts\\n * @dev to talk to Vera the verifier about the work Reggie is doing, to provide\\n * @dev simple access to a verifiable source of randomness. It ensures 2 things:\\n * @dev 1. The fulfillment came from the VRFCoordinatorV2Plus.\\n * @dev 2. The consumer contract implements fulfillRandomWords.\\n * *****************************************************************************\\n * @dev USAGE\\n *\\n * @dev Calling contracts must inherit from VRFConsumerBaseV2Plus, and can\\n * @dev initialize VRFConsumerBaseV2Plus's attributes in their constructor as\\n * @dev shown:\\n *\\n * @dev contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus {\\n * @dev constructor(, address _vrfCoordinator, address _subOwner)\\n * @dev VRFConsumerBaseV2Plus(_vrfCoordinator, _subOwner) public {\\n * @dev \\n * @dev }\\n * @dev }\\n *\\n * @dev The oracle will have given you an ID for the VRF keypair they have\\n * @dev committed to (let's call it keyHash). Create a subscription, fund it\\n * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface\\n * @dev subscription management functions).\\n * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,\\n * @dev callbackGasLimit, numWords, extraArgs),\\n * @dev see (IVRFCoordinatorV2Plus for a description of the arguments).\\n *\\n * @dev Once the VRFCoordinatorV2Plus has received and validated the oracle's response\\n * @dev to your request, it will call your contract's fulfillRandomWords method.\\n *\\n * @dev The randomness argument to fulfillRandomWords is a set of random words\\n * @dev generated from your requestId and the blockHash of the request.\\n *\\n * @dev If your contract could have concurrent requests open, you can use the\\n * @dev requestId returned from requestRandomWords to track which response is associated\\n * @dev with which randomness request.\\n * @dev See \\\"SECURITY CONSIDERATIONS\\\" for principles to keep in mind,\\n * @dev if your contract could have multiple requests in flight simultaneously.\\n *\\n * @dev Colliding `requestId`s are cryptographically impossible as long as seeds\\n * @dev differ.\\n *\\n * *****************************************************************************\\n * @dev SECURITY CONSIDERATIONS\\n *\\n * @dev A method with the ability to call your fulfillRandomness method directly\\n * @dev could spoof a VRF response with any random value, so it's critical that\\n * @dev it cannot be directly called by anything other than this base contract\\n * @dev (specifically, by the VRFConsumerBaseV2Plus.rawFulfillRandomness method).\\n *\\n * @dev For your users to trust that your contract's random behavior is free\\n * @dev from malicious interference, it's best if you can write it so that all\\n * @dev behaviors implied by a VRF response are executed *during* your\\n * @dev fulfillRandomness method. If your contract must store the response (or\\n * @dev anything derived from it) and use it later, you must ensure that any\\n * @dev user-significant behavior which depends on that stored value cannot be\\n * @dev manipulated by a subsequent VRF request.\\n *\\n * @dev Similarly, both miners and the VRF oracle itself have some influence\\n * @dev over the order in which VRF responses appear on the blockchain, so if\\n * @dev your contract could have multiple VRF requests in flight simultaneously,\\n * @dev you must ensure that the order in which the VRF responses arrive cannot\\n * @dev be used to manipulate your contract's user-significant behavior.\\n *\\n * @dev Since the block hash of the block which contains the requestRandomness\\n * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful\\n * @dev miner could, in principle, fork the blockchain to evict the block\\n * @dev containing the request, forcing the request to be included in a\\n * @dev different block with a different hash, and therefore a different input\\n * @dev to the VRF. However, such an attack would incur a substantial economic\\n * @dev cost. This cost scales with the number of blocks the VRF oracle waits\\n * @dev until it calls responds to a request. It is for this reason that\\n * @dev that you can signal to an oracle you'd like them to wait longer before\\n * @dev responding to the request (however this is not enforced in the contract\\n * @dev and so remains effective only in the case of unmodified oracle software).\\n */\\nabstract contract VRFConsumerBaseV2Plus is IVRFMigratableConsumerV2Plus, ConfirmedOwner {\\n error OnlyCoordinatorCanFulfill(address have, address want);\\n error OnlyOwnerOrCoordinator(address have, address owner, address coordinator);\\n error ZeroAddress();\\n\\n // s_vrfCoordinator should be used by consumers to make requests to vrfCoordinator\\n // so that coordinator reference is updated after migration\\n IVRFCoordinatorV2Plus public s_vrfCoordinator;\\n\\n /**\\n * @param _vrfCoordinator address of VRFCoordinator contract\\n */\\n constructor(address _vrfCoordinator) ConfirmedOwner(msg.sender) {\\n if (_vrfCoordinator == address(0)) {\\n revert ZeroAddress();\\n }\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n }\\n\\n /**\\n * @notice fulfillRandomness handles the VRF response. Your contract must\\n * @notice implement it. See \\\"SECURITY CONSIDERATIONS\\\" above for important\\n * @notice principles to keep in mind when implementing your fulfillRandomness\\n * @notice method.\\n *\\n * @dev VRFConsumerBaseV2Plus expects its subcontracts to have a method with this\\n * @dev signature, and will call it once it has verified the proof\\n * @dev associated with the randomness. (It is triggered via a call to\\n * @dev rawFulfillRandomness, below.)\\n *\\n * @param requestId The Id initially returned by requestRandomness\\n * @param randomWords the VRF output expanded to the requested number of words\\n */\\n // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\\n function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal virtual;\\n\\n // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF\\n // proof. rawFulfillRandomness then calls fulfillRandomness, after validating\\n // the origin of the call\\n function rawFulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) external {\\n if (msg.sender != address(s_vrfCoordinator)) {\\n revert OnlyCoordinatorCanFulfill(msg.sender, address(s_vrfCoordinator));\\n }\\n fulfillRandomWords(requestId, randomWords);\\n }\\n\\n /**\\n * @inheritdoc IVRFMigratableConsumerV2Plus\\n */\\n function setCoordinator(address _vrfCoordinator) external override onlyOwnerOrCoordinator {\\n if (_vrfCoordinator == address(0)) {\\n revert ZeroAddress();\\n }\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n\\n emit CoordinatorSet(_vrfCoordinator);\\n }\\n\\n modifier onlyOwnerOrCoordinator() {\\n if (msg.sender != owner() && msg.sender != address(s_vrfCoordinator)) {\\n revert OnlyOwnerOrCoordinator(msg.sender, owner(), address(s_vrfCoordinator));\\n }\\n _;\\n }\\n}\\n\",\"keccak256\":\"0x0c92838396c5abe72754ebeae526a0434dd53fdaf63e6b98111aebd6114cfcc2\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {VRFV2PlusClient} from \\\"../libraries/VRFV2PlusClient.sol\\\";\\nimport {IVRFSubscriptionV2Plus} from \\\"./IVRFSubscriptionV2Plus.sol\\\";\\n\\n// Interface that enables consumers of VRFCoordinatorV2Plus to be future-proof for upgrades\\n// This interface is supported by subsequent versions of VRFCoordinatorV2Plus\\ninterface IVRFCoordinatorV2Plus is IVRFSubscriptionV2Plus {\\n /**\\n * @notice Request a set of random words.\\n * @param req - a struct containing following fields for randomness request:\\n * keyHash - Corresponds to a particular oracle job which uses\\n * that key for generating the VRF proof. Different keyHash's have different gas price\\n * ceilings, so you can select a specific one to bound your maximum per request cost.\\n * subId - The ID of the VRF subscription. Must be funded\\n * with the minimum subscription balance required for the selected keyHash.\\n * requestConfirmations - How many blocks you'd like the\\n * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS\\n * for why you may want to request more. The acceptable range is\\n * [minimumRequestBlockConfirmations, 200].\\n * callbackGasLimit - How much gas you'd like to receive in your\\n * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords\\n * may be slightly less than this amount because of gas used calling the function\\n * (argument decoding etc.), so you may need to request slightly more than you expect\\n * to have inside fulfillRandomWords. The acceptable range is\\n * [0, maxGasLimit]\\n * numWords - The number of uint256 random values you'd like to receive\\n * in your fulfillRandomWords callback. Note these numbers are expanded in a\\n * secure way by the VRFCoordinator from a single random value supplied by the oracle.\\n * extraArgs - abi-encoded extra args\\n * @return requestId - A unique identifier of the request. Can be used to match\\n * a request to a response in fulfillRandomWords.\\n */\\n function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId);\\n}\\n\",\"keccak256\":\"0x7dca2a64690ddd95ee05e422e1f61e7c1d701aaf5be1390ae12e9bd144266c36\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice The IVRFMigratableConsumerV2Plus interface defines the\\n/// @notice method required to be implemented by all V2Plus consumers.\\n/// @dev This interface is designed to be used in VRFConsumerBaseV2Plus.\\ninterface IVRFMigratableConsumerV2Plus {\\n event CoordinatorSet(address vrfCoordinator);\\n\\n /// @notice Sets the VRF Coordinator address\\n /// @notice This method should only be callable by the coordinator or contract owner\\n function setCoordinator(address vrfCoordinator) external;\\n}\\n\",\"keccak256\":\"0x8be8744e3b8380dc85354cf110e8caef8f394266e79120ad675a7da835ed2a85\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice The IVRFSubscriptionV2Plus interface defines the subscription\\n/// @notice related methods implemented by the V2Plus coordinator.\\ninterface IVRFSubscriptionV2Plus {\\n /**\\n * @notice Add a consumer to a VRF subscription.\\n * @param subId - ID of the subscription\\n * @param consumer - New consumer which can use the subscription\\n */\\n function addConsumer(uint256 subId, address consumer) external;\\n\\n /**\\n * @notice Remove a consumer from a VRF subscription.\\n * @param subId - ID of the subscription\\n * @param consumer - Consumer to remove from the subscription\\n */\\n function removeConsumer(uint256 subId, address consumer) external;\\n\\n /**\\n * @notice Cancel a subscription\\n * @param subId - ID of the subscription\\n * @param to - Where to send the remaining LINK to\\n */\\n function cancelSubscription(uint256 subId, address to) external;\\n\\n /**\\n * @notice Accept subscription owner transfer.\\n * @param subId - ID of the subscription\\n * @dev will revert if original owner of subId has\\n * not requested that msg.sender become the new owner.\\n */\\n function acceptSubscriptionOwnerTransfer(uint256 subId) external;\\n\\n /**\\n * @notice Request subscription owner transfer.\\n * @param subId - ID of the subscription\\n * @param newOwner - proposed new owner of the subscription\\n */\\n function requestSubscriptionOwnerTransfer(uint256 subId, address newOwner) external;\\n\\n /**\\n * @notice Create a VRF subscription.\\n * @return subId - A unique subscription id.\\n * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.\\n * @dev Note to fund the subscription with LINK, use transferAndCall. For example\\n * @dev LINKTOKEN.transferAndCall(\\n * @dev address(COORDINATOR),\\n * @dev amount,\\n * @dev abi.encode(subId));\\n * @dev Note to fund the subscription with Native, use fundSubscriptionWithNative. Be sure\\n * @dev to send Native with the call, for example:\\n * @dev COORDINATOR.fundSubscriptionWithNative{value: amount}(subId);\\n */\\n function createSubscription() external returns (uint256 subId);\\n\\n /**\\n * @notice Get a VRF subscription.\\n * @param subId - ID of the subscription\\n * @return balance - LINK balance of the subscription in juels.\\n * @return nativeBalance - native balance of the subscription in wei.\\n * @return reqCount - Requests count of subscription.\\n * @return owner - owner of the subscription.\\n * @return consumers - list of consumer address which are able to use this subscription.\\n */\\n function getSubscription(\\n uint256 subId\\n )\\n external\\n view\\n returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers);\\n\\n /*\\n * @notice Check to see if there exists a request commitment consumers\\n * for all consumers and keyhashes for a given sub.\\n * @param subId - ID of the subscription\\n * @return true if there exists at least one unfulfilled request for the subscription, false\\n * otherwise.\\n */\\n function pendingRequestExists(uint256 subId) external view returns (bool);\\n\\n /**\\n * @notice Paginate through all active VRF subscriptions.\\n * @param startIndex index of the subscription to start from\\n * @param maxCount maximum number of subscriptions to return, 0 to return all\\n * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one\\n * @dev should consider keeping the blockheight constant to ensure a holistic picture of the contract state\\n */\\n function getActiveSubscriptionIds(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory);\\n\\n /**\\n * @notice Fund a subscription with native.\\n * @param subId - ID of the subscription\\n * @notice This method expects msg.value to be greater than or equal to 0.\\n */\\n function fundSubscriptionWithNative(uint256 subId) external payable;\\n}\\n\",\"keccak256\":\"0x85b348297ce36794e3bf97a47c001fc216bd0ee243e91514a7b395f3fcd189b0\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n// End consumer library.\\nlibrary VRFV2PlusClient {\\n // extraArgs will evolve to support new features\\n bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256(\\\"VRF ExtraArgsV1\\\"));\\n struct ExtraArgsV1 {\\n bool nativePayment;\\n }\\n\\n struct RandomWordsRequest {\\n bytes32 keyHash;\\n uint256 subId;\\n uint16 requestConfirmations;\\n uint32 callbackGasLimit;\\n uint32 numWords;\\n bytes extraArgs;\\n }\\n\\n function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {\\n return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs);\\n }\\n}\\n\",\"keccak256\":\"0x839ad7a737ef18147b518b4ec3cbaf4a49dc994db65cf8369ed4e69d169a98a6\",\"license\":\"MIT\"},\"src/rng/ChainlinkRNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport {VRFConsumerBaseV2Plus, IVRFCoordinatorV2Plus} from \\\"@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol\\\";\\nimport {VRFV2PlusClient} from \\\"@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol\\\";\\n\\nimport \\\"./RNG.sol\\\";\\n\\n/// @title Random Number Generator that uses Chainlink VRF v2.5\\n/// https://blog.chain.link/introducing-vrf-v2-5/\\ncontract ChainlinkRNG is RNG, VRFConsumerBaseV2Plus {\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n address public governor; // The address that can withdraw funds.\\n address public sortitionModule; // The address of the SortitionModule.\\n bytes32 public keyHash; // The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\\n uint256 public subscriptionId; // The unique identifier of the subscription used for funding requests.\\n uint16 public requestConfirmations; // How many confirmations the Chainlink node should wait before responding.\\n // 22 bytes remaining in slot\\n uint32 public callbackGasLimit; // Gas limit for the Chainlink callback.\\n uint256 public lastRequestId; // The last request ID.\\n mapping(uint256 requestId => uint256 number) public randomNumbers; // randomNumbers[requestID] is the random number for this request id, 0 otherwise.\\n\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev Emitted when a request is sent to the VRF Coordinator\\n /// @param requestId The ID of the request\\n event RequestSent(uint256 indexed requestId);\\n\\n /// Emitted when a request has been fulfilled.\\n /// @param requestId The ID of the request\\n /// @param randomWord The random value answering the request.\\n event RequestFulfilled(uint256 indexed requestId, uint256 randomWord);\\n\\n // ************************************* //\\n // * Function Modifiers * //\\n // ************************************* //\\n\\n modifier onlyByGovernor() {\\n require(governor == msg.sender, \\\"Governor only\\\");\\n _;\\n }\\n\\n modifier onlyBySortitionModule() {\\n require(sortitionModule == msg.sender, \\\"SortitionModule only\\\");\\n _;\\n }\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor, initializing the implementation to reduce attack surface.\\n /// @param _governor The Governor of the contract.\\n /// @param _sortitionModule The address of the SortitionModule contract.\\n /// @param _vrfCoordinator The address of the VRFCoordinator contract.\\n /// @param _keyHash The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\\n /// @param _subscriptionId The unique identifier of the subscription used for funding requests.\\n /// @param _requestConfirmations How many confirmations the Chainlink node should wait before responding.\\n /// @param _callbackGasLimit The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.\\n /// @dev https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number\\n constructor(\\n address _governor,\\n address _sortitionModule,\\n address _vrfCoordinator,\\n bytes32 _keyHash,\\n uint256 _subscriptionId,\\n uint16 _requestConfirmations,\\n uint32 _callbackGasLimit\\n ) VRFConsumerBaseV2Plus(_vrfCoordinator) {\\n governor = _governor;\\n sortitionModule = _sortitionModule;\\n keyHash = _keyHash;\\n subscriptionId = _subscriptionId;\\n requestConfirmations = _requestConfirmations;\\n callbackGasLimit = _callbackGasLimit;\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n /// @dev Changes the governor of the contract.\\n /// @param _governor The new governor.\\n function changeGovernor(address _governor) external onlyByGovernor {\\n governor = _governor;\\n }\\n\\n /// @dev Changes the sortition module of the contract.\\n /// @param _sortitionModule The new sortition module.\\n function changeSortitionModule(address _sortitionModule) external onlyByGovernor {\\n sortitionModule = _sortitionModule;\\n }\\n\\n /// @dev Changes the VRF Coordinator of the contract.\\n /// @param _vrfCoordinator The new VRF Coordinator.\\n function changeVrfCoordinator(address _vrfCoordinator) external onlyByGovernor {\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n emit CoordinatorSet(_vrfCoordinator);\\n }\\n\\n /// @dev Changes the key hash of the contract.\\n /// @param _keyHash The new key hash.\\n function changeKeyHash(bytes32 _keyHash) external onlyByGovernor {\\n keyHash = _keyHash;\\n }\\n\\n /// @dev Changes the subscription ID of the contract.\\n /// @param _subscriptionId The new subscription ID.\\n function changeSubscriptionId(uint256 _subscriptionId) external onlyByGovernor {\\n subscriptionId = _subscriptionId;\\n }\\n\\n /// @dev Changes the request confirmations of the contract.\\n /// @param _requestConfirmations The new request confirmations.\\n function changeRequestConfirmations(uint16 _requestConfirmations) external onlyByGovernor {\\n requestConfirmations = _requestConfirmations;\\n }\\n\\n /// @dev Changes the callback gas limit of the contract.\\n /// @param _callbackGasLimit The new callback gas limit.\\n function changeCallbackGasLimit(uint32 _callbackGasLimit) external onlyByGovernor {\\n callbackGasLimit = _callbackGasLimit;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Request a random number. SortitionModule only.\\n function requestRandomness(uint256 /*_block*/) external override onlyBySortitionModule {\\n // Will revert if subscription is not set and funded.\\n uint256 requestId = s_vrfCoordinator.requestRandomWords(\\n VRFV2PlusClient.RandomWordsRequest({\\n keyHash: keyHash,\\n subId: subscriptionId,\\n requestConfirmations: requestConfirmations,\\n callbackGasLimit: callbackGasLimit,\\n numWords: 1,\\n extraArgs: VRFV2PlusClient._argsToBytes(\\n // Set nativePayment to true to pay for VRF requests with ETH instead of LINK\\n VRFV2PlusClient.ExtraArgsV1({nativePayment: true})\\n )\\n })\\n );\\n lastRequestId = requestId;\\n emit RequestSent(requestId);\\n }\\n\\n /// @dev Callback function called by the VRF Coordinator when the random value is generated.\\n /// @param _requestId The ID of the request.\\n /// @param _randomWords The random values answering the request.\\n function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) internal override {\\n // Access control is handled by the parent VRFCoordinator.rawFulfillRandomWords()\\n randomNumbers[_requestId] = _randomWords[0];\\n emit RequestFulfilled(_requestId, _randomWords[0]);\\n }\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @dev Return the random number.\\n /// @return randomNumber The random number or 0 if it is not ready or has not been requested.\\n function receiveRandomness(uint256 /*_block*/) external view override returns (uint256 randomNumber) {\\n randomNumber = randomNumbers[lastRequestId];\\n }\\n}\\n\",\"keccak256\":\"0xf132cbbbbb47a4f11c248fab30212a3dd3e7b20b1bc5b543ff21b6d291367dc8\",\"license\":\"MIT\"},\"src/rng/RNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\ninterface RNG {\\n /// @dev Request a random number.\\n /// @param _block Block linked to the request.\\n function requestRandomness(uint256 _block) external;\\n\\n /// @dev Receive the random number.\\n /// @param _block Block the random number is linked to.\\n /// @return randomNumber Random Number. If the number is not ready or has not been required 0 instead.\\n function receiveRandomness(uint256 _block) external returns (uint256 randomNumber);\\n}\\n\",\"keccak256\":\"0xf92e0cf768afefc5cc6ef786c263b67dd00c021aa5753213dbbc33014adb68c5\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162000f6038038062000f6083398101604081905262000034916200022d565b8433806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000165565b5050506001600160a01b038116620000ea5760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b03199081166001600160a01b03938416179091556003805482169983169990991790985560048054909816961695909517909555600591909155600655506007805461ffff90931665ffffffffffff19909316929092176201000063ffffffff90921691909102179055620002c5565b336001600160a01b03821603620001bf5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200022857600080fd5b919050565b600080600080600080600060e0888a0312156200024957600080fd5b620002548862000210565b9650620002646020890162000210565b9550620002746040890162000210565b9450606088015193506080880151925060a088015161ffff811681146200029a57600080fd5b60c089015190925063ffffffff81168114620002b557600080fd5b8091505092959891949750929550565b610c8b80620002d56000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c806379ba5097116100c3578063e4c0aaf41161007c578063e4c0aaf4146102e5578063e86a51cb146102f8578063f2fde38b1461030b578063f50d390d1461031e578063f9f5dd9114610331578063fc2a88c31461034457600080fd5b806379ba5097146102725780638da5cb5b1461027a5780638ea981171461028b5780639eccacf61461029e578063b0049637146102b1578063b0fb162f146102c457600080fd5b80632e1daf2f116101155780632e1daf2f146101fd5780632f68f4821461021057806339b1e245146102235780635257cd901461023657806361728f39146102565780637363ae1f1461025f57600080fd5b806309c1ba2e146101525780630c340a241461016e57806313cf9054146101995780631fe543e3146101bd57806324f74697146101d2575b600080fd5b61015b60065481565b6040519081526020015b60405180910390f35b600354610181906001600160a01b031681565b6040516001600160a01b039091168152602001610165565b61015b6101a7366004610a4f565b5060085460009081526009602052604090205490565b6101d06101cb366004610a68565b61034d565b005b6007546101e89062010000900463ffffffff1681565b60405163ffffffff9091168152602001610165565b600454610181906001600160a01b031681565b6101d061021e366004610a4f565b6103a2565b6101d0610231366004610a4f565b6103d1565b61015b610244366004610a4f565b60096020526000908152604090205481565b61015b60055481565b6101d061026d366004610a4f565b610400565b6101d061055b565b6000546001600160a01b0316610181565b6101d0610299366004610ae7565b610605565b600254610181906001600160a01b031681565b6101d06102bf366004610ae7565b6106f7565b6007546102d29061ffff1681565b60405161ffff9091168152602001610165565b6101d06102f3366004610ae7565b610743565b6101d0610306366004610b17565b61078f565b6101d0610319366004610ae7565b6107dd565b6101d061032c366004610b3d565b6107f1565b6101d061033f366004610ae7565b610833565b61015b60085481565b6002546001600160a01b031633146103925760025460405163073e64fd60e21b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b61039d83838361085d565b505050565b6003546001600160a01b031633146103cc5760405162461bcd60e51b815260040161038990610b61565b600555565b6003546001600160a01b031633146103fb5760405162461bcd60e51b815260040161038990610b61565b600655565b6004546001600160a01b031633146104515760405162461bcd60e51b8152602060048201526014602482015273536f72746974696f6e4d6f64756c65206f6e6c7960601b6044820152606401610389565b6002546040805160c081018252600554815260065460208083019190915260075461ffff81168385015262010000900463ffffffff16606083015260016080830181905283519182019093529182526000926001600160a01b031691639b1c385e919060a08201906104c2906108e6565b8152506040518263ffffffff1660e01b81526004016104e19190610b88565b6020604051808303816000875af1158015610500573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105249190610c26565b600881905560405190915081907f0cd21a41891ff04ecd9a8754bec97e2fb85d2a4e7694329d4dc364c796f23d0690600090a25050565b6001546001600160a01b031633146105ae5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610389565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331480159061062b57506002546001600160a01b03163314155b1561067c57336106436000546001600160a01b031690565b60025460405163061db9c160e01b81526001600160a01b0393841660048201529183166024830152919091166044820152606401610389565b6001600160a01b0381166106a35760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be69060200160405180910390a150565b6003546001600160a01b031633146107215760405162461bcd60e51b815260040161038990610b61565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b0316331461076d5760405162461bcd60e51b815260040161038990610b61565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107b95760405162461bcd60e51b815260040161038990610b61565b6007805463ffffffff909216620100000265ffffffff000019909216919091179055565b6107e5610957565b6107ee816109ac565b50565b6003546001600160a01b0316331461081b5760405162461bcd60e51b815260040161038990610b61565b6007805461ffff191661ffff92909216919091179055565b6003546001600160a01b031633146106a35760405162461bcd60e51b815260040161038990610b61565b8181600081811061087057610870610c3f565b905060200201356009600085815260200190815260200160002081905550827f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d5838360008181106108c3576108c3610c3f565b905060200201356040516108d991815260200190565b60405180910390a2505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161091f91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000546001600160a01b031633146109aa5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610389565b565b336001600160a01b038216036109fe5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610389565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a6157600080fd5b5035919050565b600080600060408486031215610a7d57600080fd5b83359250602084013567ffffffffffffffff80821115610a9c57600080fd5b818601915086601f830112610ab057600080fd5b813581811115610abf57600080fd5b8760208260051b8501011115610ad457600080fd5b6020830194508093505050509250925092565b600060208284031215610af957600080fd5b81356001600160a01b0381168114610b1057600080fd5b9392505050565b600060208284031215610b2957600080fd5b813563ffffffff81168114610b1057600080fd5b600060208284031215610b4f57600080fd5b813561ffff81168114610b1057600080fd5b6020808252600d908201526c476f7665726e6f72206f6e6c7960981b604082015260600190565b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015610c015782810184015186820161010001528301610be4565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610c3857600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fdfea26469706673582212201c20e67178fd79424f46cb830b3496516dfa70ea88c1d07b59de6b70b0f17ca764736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061014d5760003560e01c806379ba5097116100c3578063e4c0aaf41161007c578063e4c0aaf4146102e5578063e86a51cb146102f8578063f2fde38b1461030b578063f50d390d1461031e578063f9f5dd9114610331578063fc2a88c31461034457600080fd5b806379ba5097146102725780638da5cb5b1461027a5780638ea981171461028b5780639eccacf61461029e578063b0049637146102b1578063b0fb162f146102c457600080fd5b80632e1daf2f116101155780632e1daf2f146101fd5780632f68f4821461021057806339b1e245146102235780635257cd901461023657806361728f39146102565780637363ae1f1461025f57600080fd5b806309c1ba2e146101525780630c340a241461016e57806313cf9054146101995780631fe543e3146101bd57806324f74697146101d2575b600080fd5b61015b60065481565b6040519081526020015b60405180910390f35b600354610181906001600160a01b031681565b6040516001600160a01b039091168152602001610165565b61015b6101a7366004610a4f565b5060085460009081526009602052604090205490565b6101d06101cb366004610a68565b61034d565b005b6007546101e89062010000900463ffffffff1681565b60405163ffffffff9091168152602001610165565b600454610181906001600160a01b031681565b6101d061021e366004610a4f565b6103a2565b6101d0610231366004610a4f565b6103d1565b61015b610244366004610a4f565b60096020526000908152604090205481565b61015b60055481565b6101d061026d366004610a4f565b610400565b6101d061055b565b6000546001600160a01b0316610181565b6101d0610299366004610ae7565b610605565b600254610181906001600160a01b031681565b6101d06102bf366004610ae7565b6106f7565b6007546102d29061ffff1681565b60405161ffff9091168152602001610165565b6101d06102f3366004610ae7565b610743565b6101d0610306366004610b17565b61078f565b6101d0610319366004610ae7565b6107dd565b6101d061032c366004610b3d565b6107f1565b6101d061033f366004610ae7565b610833565b61015b60085481565b6002546001600160a01b031633146103925760025460405163073e64fd60e21b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b61039d83838361085d565b505050565b6003546001600160a01b031633146103cc5760405162461bcd60e51b815260040161038990610b61565b600555565b6003546001600160a01b031633146103fb5760405162461bcd60e51b815260040161038990610b61565b600655565b6004546001600160a01b031633146104515760405162461bcd60e51b8152602060048201526014602482015273536f72746974696f6e4d6f64756c65206f6e6c7960601b6044820152606401610389565b6002546040805160c081018252600554815260065460208083019190915260075461ffff81168385015262010000900463ffffffff16606083015260016080830181905283519182019093529182526000926001600160a01b031691639b1c385e919060a08201906104c2906108e6565b8152506040518263ffffffff1660e01b81526004016104e19190610b88565b6020604051808303816000875af1158015610500573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105249190610c26565b600881905560405190915081907f0cd21a41891ff04ecd9a8754bec97e2fb85d2a4e7694329d4dc364c796f23d0690600090a25050565b6001546001600160a01b031633146105ae5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610389565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331480159061062b57506002546001600160a01b03163314155b1561067c57336106436000546001600160a01b031690565b60025460405163061db9c160e01b81526001600160a01b0393841660048201529183166024830152919091166044820152606401610389565b6001600160a01b0381166106a35760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be69060200160405180910390a150565b6003546001600160a01b031633146107215760405162461bcd60e51b815260040161038990610b61565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b0316331461076d5760405162461bcd60e51b815260040161038990610b61565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107b95760405162461bcd60e51b815260040161038990610b61565b6007805463ffffffff909216620100000265ffffffff000019909216919091179055565b6107e5610957565b6107ee816109ac565b50565b6003546001600160a01b0316331461081b5760405162461bcd60e51b815260040161038990610b61565b6007805461ffff191661ffff92909216919091179055565b6003546001600160a01b031633146106a35760405162461bcd60e51b815260040161038990610b61565b8181600081811061087057610870610c3f565b905060200201356009600085815260200190815260200160002081905550827f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d5838360008181106108c3576108c3610c3f565b905060200201356040516108d991815260200190565b60405180910390a2505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161091f91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000546001600160a01b031633146109aa5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610389565b565b336001600160a01b038216036109fe5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610389565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a6157600080fd5b5035919050565b600080600060408486031215610a7d57600080fd5b83359250602084013567ffffffffffffffff80821115610a9c57600080fd5b818601915086601f830112610ab057600080fd5b813581811115610abf57600080fd5b8760208260051b8501011115610ad457600080fd5b6020830194508093505050509250925092565b600060208284031215610af957600080fd5b81356001600160a01b0381168114610b1057600080fd5b9392505050565b600060208284031215610b2957600080fd5b813563ffffffff81168114610b1057600080fd5b600060208284031215610b4f57600080fd5b813561ffff81168114610b1057600080fd5b6020808252600d908201526c476f7665726e6f72206f6e6c7960981b604082015260600190565b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015610c015782810184015186820161010001528301610be4565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610c3857600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fdfea26469706673582212201c20e67178fd79424f46cb830b3496516dfa70ea88c1d07b59de6b70b0f17ca764736f6c63430008180033", + "devdoc": { + "events": { + "RequestFulfilled(uint256,uint256)": { + "params": { + "randomWord": "The random value answering the request.", + "requestId": "The ID of the request" + } + }, + "RequestSent(uint256)": { + "details": "Emitted when a request is sent to the VRF Coordinator", + "params": { + "requestId": "The ID of the request" + } + } + }, + "kind": "dev", + "methods": { + "changeCallbackGasLimit(uint32)": { + "details": "Changes the callback gas limit of the contract.", + "params": { + "_callbackGasLimit": "The new callback gas limit." + } + }, + "changeGovernor(address)": { + "details": "Changes the governor of the contract.", + "params": { + "_governor": "The new governor." + } + }, + "changeKeyHash(bytes32)": { + "details": "Changes the key hash of the contract.", + "params": { + "_keyHash": "The new key hash." + } + }, + "changeRequestConfirmations(uint16)": { + "details": "Changes the request confirmations of the contract.", + "params": { + "_requestConfirmations": "The new request confirmations." + } + }, + "changeSortitionModule(address)": { + "details": "Changes the sortition module of the contract.", + "params": { + "_sortitionModule": "The new sortition module." + } + }, + "changeSubscriptionId(uint256)": { + "details": "Changes the subscription ID of the contract.", + "params": { + "_subscriptionId": "The new subscription ID." + } + }, + "changeVrfCoordinator(address)": { + "details": "Changes the VRF Coordinator of the contract.", + "params": { + "_vrfCoordinator": "The new VRF Coordinator." + } + }, + "constructor": { + "details": "Constructor, initializing the implementation to reduce attack surface.https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number", + "params": { + "_callbackGasLimit": "The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.", + "_governor": "The Governor of the contract.", + "_keyHash": "The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).", + "_requestConfirmations": "How many confirmations the Chainlink node should wait before responding.", + "_sortitionModule": "The address of the SortitionModule contract.", + "_subscriptionId": "The unique identifier of the subscription used for funding requests.", + "_vrfCoordinator": "The address of the VRFCoordinator contract." + } + }, + "receiveRandomness(uint256)": { + "details": "Return the random number.", + "returns": { + "randomNumber": "The random number or 0 if it is not ready or has not been requested." + } + }, + "requestRandomness(uint256)": { + "details": "Request a random number. SortitionModule only." + } + }, + "title": "Random Number Generator that uses Chainlink VRF v2.5 https://blog.chain.link/introducing-vrf-v2-5/", + "version": 1 + }, + "userdoc": { + "events": { + "RequestFulfilled(uint256,uint256)": { + "notice": "Emitted when a request has been fulfilled." + } + }, + "kind": "user", + "methods": { + "acceptOwnership()": { + "notice": "Allows an ownership transfer to be completed by the recipient." + }, + "owner()": { + "notice": "Get the current owner" + }, + "setCoordinator(address)": { + "notice": "Sets the VRF Coordinator addressThis method should only be callable by the coordinator or contract owner" + }, + "transferOwnership(address)": { + "notice": "Allows an owner to begin transferring ownership to a new address." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 29, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "s_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 31, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "s_pendingOwner", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 231, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "s_vrfCoordinator", + "offset": 0, + "slot": "2", + "type": "t_contract(IVRFCoordinatorV2Plus)380" + }, + { + "astId": 35404, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "governor", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 35406, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "sortitionModule", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 35408, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "keyHash", + "offset": 0, + "slot": "5", + "type": "t_bytes32" + }, + { + "astId": 35410, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "subscriptionId", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 35412, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "requestConfirmations", + "offset": 0, + "slot": "7", + "type": "t_uint16" + }, + { + "astId": 35414, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "callbackGasLimit", + "offset": 2, + "slot": "7", + "type": "t_uint32" + }, + { + "astId": 35416, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "lastRequestId", + "offset": 0, + "slot": "8", + "type": "t_uint256" + }, + { + "astId": 35420, + "contract": "src/rng/ChainlinkRNG.sol:ChainlinkRNG", + "label": "randomNumbers", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_uint256,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IVRFCoordinatorV2Plus)380": { + "encoding": "inplace", + "label": "contract IVRFCoordinatorV2Plus", + "numberOfBytes": "20" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint16": { + "encoding": "inplace", + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + } + } + } +} diff --git a/contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json b/contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json index 589a64d7f..2430ef919 100644 --- a/contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json +++ b/contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json @@ -1,5 +1,5 @@ { - "address": "0x1ce7F5771bA530a6b2d7129268E0c04441DF95c9", + "address": "0x6c40D7F5d5bE3492fe9EF70e4eCb2BD773c12AF8", "abi": [ { "inputs": [ @@ -304,6 +304,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "owner", @@ -465,19 +478,19 @@ "type": "function" } ], - "transactionHash": "0x98e0e5095a628df19a3987f45637207b99ec2e91a7fdfc335244f625ca1faac2", + "transactionHash": "0xd5e7edface8b81d4d2927d37ab047c466629fda2d99d3f571ebc557d706c6226", "receipt": { "to": null, "from": "0xf1C7c037891525E360C59f708739Ac09A7670c59", - "contractAddress": "0x1ce7F5771bA530a6b2d7129268E0c04441DF95c9", + "contractAddress": "0x6c40D7F5d5bE3492fe9EF70e4eCb2BD773c12AF8", "transactionIndex": 1, - "gasUsed": "925617", + "gasUsed": "1671702", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3b1792895296c1c77836af5d139a7883f2abdfc845856c7486214d4fb826f768", - "transactionHash": "0x98e0e5095a628df19a3987f45637207b99ec2e91a7fdfc335244f625ca1faac2", + "blockHash": "0x5b634d70e2ef30415cc7907f2466dc05747f3724793ac53366d7d6e52de7d438", + "transactionHash": "0xd5e7edface8b81d4d2927d37ab047c466629fda2d99d3f571ebc557d706c6226", "logs": [], - "blockNumber": 104436407, - "cumulativeGasUsed": "925617", + "blockNumber": 105821763, + "cumulativeGasUsed": "1671702", "status": 1, "byzantium": true }, @@ -487,14 +500,14 @@ "0x5CE8D5A2BC84beb22a398CCA51996F7930313D61", "0x1770bdc7eec7771f7ba4ffd640f34260d7f095b79c92d34a5b2551d6f6cfd2be", "38502597312983100069991953687934627561654236680431968938019951490339399569548", - 20, + 200, 100000 ], - "numDeployments": 1, - "solcInputHash": "75a40fe267f89917a94a61837d7b8dfe", - "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_sortitionModule\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_subscriptionId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"want\",\"type\":\"address\"}],\"name\":\"OnlyCoordinatorCanFulfill\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"OnlyOwnerOrCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vrfCoordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"randomWord\",\"type\":\"uint256\"}],\"name\":\"RequestFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"RequestSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"callbackGasLimit\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"name\":\"changeCallbackGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"}],\"name\":\"changeKeyHash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"}],\"name\":\"changeRequestConfirmations\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sortitionModule\",\"type\":\"address\"}],\"name\":\"changeSortitionModule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_subscriptionId\",\"type\":\"uint256\"}],\"name\":\"changeSubscriptionId\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"changeVrfCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"keyHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"randomNumbers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"receiveRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"randomNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requestConfirmations\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"requestRandomness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_vrfCoordinator\",\"outputs\":[{\"internalType\":\"contract IVRFCoordinatorV2Plus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sortitionModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"subscriptionId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"RequestFulfilled(uint256,uint256)\":{\"params\":{\"randomWord\":\"The random value answering the request.\",\"requestId\":\"The ID of the request\"}},\"RequestSent(uint256)\":{\"details\":\"Emitted when a request is sent to the VRF Coordinator\",\"params\":{\"requestId\":\"The ID of the request\"}}},\"kind\":\"dev\",\"methods\":{\"changeCallbackGasLimit(uint32)\":{\"details\":\"Changes the callback gas limit of the contract.\",\"params\":{\"_callbackGasLimit\":\"The new callback gas limit.\"}},\"changeGovernor(address)\":{\"details\":\"Changes the governor of the contract.\",\"params\":{\"_governor\":\"The new governor.\"}},\"changeKeyHash(bytes32)\":{\"details\":\"Changes the key hash of the contract.\",\"params\":{\"_keyHash\":\"The new key hash.\"}},\"changeRequestConfirmations(uint16)\":{\"details\":\"Changes the request confirmations of the contract.\",\"params\":{\"_requestConfirmations\":\"The new request confirmations.\"}},\"changeSortitionModule(address)\":{\"details\":\"Changes the sortition module of the contract.\",\"params\":{\"_sortitionModule\":\"The new sortition module.\"}},\"changeSubscriptionId(uint256)\":{\"details\":\"Changes the subscription ID of the contract.\",\"params\":{\"_subscriptionId\":\"The new subscription ID.\"}},\"changeVrfCoordinator(address)\":{\"details\":\"Changes the VRF Coordinator of the contract.\",\"params\":{\"_vrfCoordinator\":\"The new VRF Coordinator.\"}},\"constructor\":{\"details\":\"Constructor, initializing the implementation to reduce attack surface.https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number\",\"params\":{\"_callbackGasLimit\":\"The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.\",\"_governor\":\"The Governor of the contract.\",\"_keyHash\":\"The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\",\"_requestConfirmations\":\"How many confirmations the Chainlink node should wait before responding.\",\"_sortitionModule\":\"The address of the SortitionModule contract.\",\"_subscriptionId\":\"The unique identifier of the subscription used for funding requests.\",\"_vrfCoordinator\":\"The address of the VRFCoordinator contract.\"}},\"receiveRandomness(uint256)\":{\"details\":\"Return the random number.\",\"returns\":{\"randomNumber\":\"The random number or 0 if it is not ready or has not been requested.\"}},\"requestRandomness(uint256)\":{\"details\":\"Request a random number. SortitionModule only.\"}},\"title\":\"Random Number Generator that uses Chainlink VRF v2.5 https://blog.chain.link/introducing-vrf-v2-5/\",\"version\":1},\"userdoc\":{\"events\":{\"RequestFulfilled(uint256,uint256)\":{\"notice\":\"Emitted when a request has been fulfilled.\"}},\"kind\":\"user\",\"methods\":{\"acceptOwnership()\":{\"notice\":\"Allows an ownership transfer to be completed by the recipient.\"},\"owner()\":{\"notice\":\"Get the current owner\"},\"setCoordinator(address)\":{\"notice\":\"Sets the VRF Coordinator addressThis method should only be callable by the coordinator or contract owner\"},\"transferOwnership(address)\":{\"notice\":\"Allows an owner to begin transferring ownership to a new address.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/rng/ChainlinkRNG.sol\":\"ChainlinkRNG\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {ConfirmedOwnerWithProposal} from \\\"./ConfirmedOwnerWithProposal.sol\\\";\\n\\n/// @title The ConfirmedOwner contract\\n/// @notice A contract with helpers for basic contract ownership.\\ncontract ConfirmedOwner is ConfirmedOwnerWithProposal {\\n constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}\\n}\\n\",\"keccak256\":\"0xdcb0e9135ddbe71ee27ba99fa06656960c66c964cf2ecb29696da1c1427d9861\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {IOwnable} from \\\"../interfaces/IOwnable.sol\\\";\\n\\n/// @title The ConfirmedOwner contract\\n/// @notice A contract with helpers for basic contract ownership.\\ncontract ConfirmedOwnerWithProposal is IOwnable {\\n address private s_owner;\\n address private s_pendingOwner;\\n\\n event OwnershipTransferRequested(address indexed from, address indexed to);\\n event OwnershipTransferred(address indexed from, address indexed to);\\n\\n constructor(address newOwner, address pendingOwner) {\\n // solhint-disable-next-line gas-custom-errors\\n require(newOwner != address(0), \\\"Cannot set owner to zero\\\");\\n\\n s_owner = newOwner;\\n if (pendingOwner != address(0)) {\\n _transferOwnership(pendingOwner);\\n }\\n }\\n\\n /// @notice Allows an owner to begin transferring ownership to a new address.\\n function transferOwnership(address to) public override onlyOwner {\\n _transferOwnership(to);\\n }\\n\\n /// @notice Allows an ownership transfer to be completed by the recipient.\\n function acceptOwnership() external override {\\n // solhint-disable-next-line gas-custom-errors\\n require(msg.sender == s_pendingOwner, \\\"Must be proposed owner\\\");\\n\\n address oldOwner = s_owner;\\n s_owner = msg.sender;\\n s_pendingOwner = address(0);\\n\\n emit OwnershipTransferred(oldOwner, msg.sender);\\n }\\n\\n /// @notice Get the current owner\\n function owner() public view override returns (address) {\\n return s_owner;\\n }\\n\\n /// @notice validate, transfer ownership, and emit relevant events\\n function _transferOwnership(address to) private {\\n // solhint-disable-next-line gas-custom-errors\\n require(to != msg.sender, \\\"Cannot transfer to self\\\");\\n\\n s_pendingOwner = to;\\n\\n emit OwnershipTransferRequested(s_owner, to);\\n }\\n\\n /// @notice validate access\\n function _validateOwnership() internal view {\\n // solhint-disable-next-line gas-custom-errors\\n require(msg.sender == s_owner, \\\"Only callable by owner\\\");\\n }\\n\\n /// @notice Reverts if called by anyone other than the contract owner.\\n modifier onlyOwner() {\\n _validateOwnership();\\n _;\\n }\\n}\\n\",\"keccak256\":\"0x2422a055657a87e98be61f8f31abb1824ec50fd0f73949f4e3c6ac877efb6da8\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IOwnable {\\n function owner() external returns (address);\\n\\n function transferOwnership(address recipient) external;\\n\\n function acceptOwnership() external;\\n}\\n\",\"keccak256\":\"0x885de72b7b4e4f1bf8ba817a3f2bcc37fd9022d342c4ce76782151c30122d767\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {IVRFCoordinatorV2Plus} from \\\"./interfaces/IVRFCoordinatorV2Plus.sol\\\";\\nimport {IVRFMigratableConsumerV2Plus} from \\\"./interfaces/IVRFMigratableConsumerV2Plus.sol\\\";\\nimport {ConfirmedOwner} from \\\"../../shared/access/ConfirmedOwner.sol\\\";\\n\\n/** ****************************************************************************\\n * @notice Interface for contracts using VRF randomness\\n * *****************************************************************************\\n * @dev PURPOSE\\n *\\n * @dev Reggie the Random Oracle (not his real job) wants to provide randomness\\n * @dev to Vera the verifier in such a way that Vera can be sure he's not\\n * @dev making his output up to suit himself. Reggie provides Vera a public key\\n * @dev to which he knows the secret key. Each time Vera provides a seed to\\n * @dev Reggie, he gives back a value which is computed completely\\n * @dev deterministically from the seed and the secret key.\\n *\\n * @dev Reggie provides a proof by which Vera can verify that the output was\\n * @dev correctly computed once Reggie tells it to her, but without that proof,\\n * @dev the output is indistinguishable to her from a uniform random sample\\n * @dev from the output space.\\n *\\n * @dev The purpose of this contract is to make it easy for unrelated contracts\\n * @dev to talk to Vera the verifier about the work Reggie is doing, to provide\\n * @dev simple access to a verifiable source of randomness. It ensures 2 things:\\n * @dev 1. The fulfillment came from the VRFCoordinatorV2Plus.\\n * @dev 2. The consumer contract implements fulfillRandomWords.\\n * *****************************************************************************\\n * @dev USAGE\\n *\\n * @dev Calling contracts must inherit from VRFConsumerBaseV2Plus, and can\\n * @dev initialize VRFConsumerBaseV2Plus's attributes in their constructor as\\n * @dev shown:\\n *\\n * @dev contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus {\\n * @dev constructor(, address _vrfCoordinator, address _subOwner)\\n * @dev VRFConsumerBaseV2Plus(_vrfCoordinator, _subOwner) public {\\n * @dev \\n * @dev }\\n * @dev }\\n *\\n * @dev The oracle will have given you an ID for the VRF keypair they have\\n * @dev committed to (let's call it keyHash). Create a subscription, fund it\\n * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface\\n * @dev subscription management functions).\\n * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,\\n * @dev callbackGasLimit, numWords, extraArgs),\\n * @dev see (IVRFCoordinatorV2Plus for a description of the arguments).\\n *\\n * @dev Once the VRFCoordinatorV2Plus has received and validated the oracle's response\\n * @dev to your request, it will call your contract's fulfillRandomWords method.\\n *\\n * @dev The randomness argument to fulfillRandomWords is a set of random words\\n * @dev generated from your requestId and the blockHash of the request.\\n *\\n * @dev If your contract could have concurrent requests open, you can use the\\n * @dev requestId returned from requestRandomWords to track which response is associated\\n * @dev with which randomness request.\\n * @dev See \\\"SECURITY CONSIDERATIONS\\\" for principles to keep in mind,\\n * @dev if your contract could have multiple requests in flight simultaneously.\\n *\\n * @dev Colliding `requestId`s are cryptographically impossible as long as seeds\\n * @dev differ.\\n *\\n * *****************************************************************************\\n * @dev SECURITY CONSIDERATIONS\\n *\\n * @dev A method with the ability to call your fulfillRandomness method directly\\n * @dev could spoof a VRF response with any random value, so it's critical that\\n * @dev it cannot be directly called by anything other than this base contract\\n * @dev (specifically, by the VRFConsumerBaseV2Plus.rawFulfillRandomness method).\\n *\\n * @dev For your users to trust that your contract's random behavior is free\\n * @dev from malicious interference, it's best if you can write it so that all\\n * @dev behaviors implied by a VRF response are executed *during* your\\n * @dev fulfillRandomness method. If your contract must store the response (or\\n * @dev anything derived from it) and use it later, you must ensure that any\\n * @dev user-significant behavior which depends on that stored value cannot be\\n * @dev manipulated by a subsequent VRF request.\\n *\\n * @dev Similarly, both miners and the VRF oracle itself have some influence\\n * @dev over the order in which VRF responses appear on the blockchain, so if\\n * @dev your contract could have multiple VRF requests in flight simultaneously,\\n * @dev you must ensure that the order in which the VRF responses arrive cannot\\n * @dev be used to manipulate your contract's user-significant behavior.\\n *\\n * @dev Since the block hash of the block which contains the requestRandomness\\n * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful\\n * @dev miner could, in principle, fork the blockchain to evict the block\\n * @dev containing the request, forcing the request to be included in a\\n * @dev different block with a different hash, and therefore a different input\\n * @dev to the VRF. However, such an attack would incur a substantial economic\\n * @dev cost. This cost scales with the number of blocks the VRF oracle waits\\n * @dev until it calls responds to a request. It is for this reason that\\n * @dev that you can signal to an oracle you'd like them to wait longer before\\n * @dev responding to the request (however this is not enforced in the contract\\n * @dev and so remains effective only in the case of unmodified oracle software).\\n */\\nabstract contract VRFConsumerBaseV2Plus is IVRFMigratableConsumerV2Plus, ConfirmedOwner {\\n error OnlyCoordinatorCanFulfill(address have, address want);\\n error OnlyOwnerOrCoordinator(address have, address owner, address coordinator);\\n error ZeroAddress();\\n\\n // s_vrfCoordinator should be used by consumers to make requests to vrfCoordinator\\n // so that coordinator reference is updated after migration\\n IVRFCoordinatorV2Plus public s_vrfCoordinator;\\n\\n /**\\n * @param _vrfCoordinator address of VRFCoordinator contract\\n */\\n constructor(address _vrfCoordinator) ConfirmedOwner(msg.sender) {\\n if (_vrfCoordinator == address(0)) {\\n revert ZeroAddress();\\n }\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n }\\n\\n /**\\n * @notice fulfillRandomness handles the VRF response. Your contract must\\n * @notice implement it. See \\\"SECURITY CONSIDERATIONS\\\" above for important\\n * @notice principles to keep in mind when implementing your fulfillRandomness\\n * @notice method.\\n *\\n * @dev VRFConsumerBaseV2Plus expects its subcontracts to have a method with this\\n * @dev signature, and will call it once it has verified the proof\\n * @dev associated with the randomness. (It is triggered via a call to\\n * @dev rawFulfillRandomness, below.)\\n *\\n * @param requestId The Id initially returned by requestRandomness\\n * @param randomWords the VRF output expanded to the requested number of words\\n */\\n // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\\n function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal virtual;\\n\\n // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF\\n // proof. rawFulfillRandomness then calls fulfillRandomness, after validating\\n // the origin of the call\\n function rawFulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) external {\\n if (msg.sender != address(s_vrfCoordinator)) {\\n revert OnlyCoordinatorCanFulfill(msg.sender, address(s_vrfCoordinator));\\n }\\n fulfillRandomWords(requestId, randomWords);\\n }\\n\\n /**\\n * @inheritdoc IVRFMigratableConsumerV2Plus\\n */\\n function setCoordinator(address _vrfCoordinator) external override onlyOwnerOrCoordinator {\\n if (_vrfCoordinator == address(0)) {\\n revert ZeroAddress();\\n }\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n\\n emit CoordinatorSet(_vrfCoordinator);\\n }\\n\\n modifier onlyOwnerOrCoordinator() {\\n if (msg.sender != owner() && msg.sender != address(s_vrfCoordinator)) {\\n revert OnlyOwnerOrCoordinator(msg.sender, owner(), address(s_vrfCoordinator));\\n }\\n _;\\n }\\n}\\n\",\"keccak256\":\"0x0c92838396c5abe72754ebeae526a0434dd53fdaf63e6b98111aebd6114cfcc2\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {VRFV2PlusClient} from \\\"../libraries/VRFV2PlusClient.sol\\\";\\nimport {IVRFSubscriptionV2Plus} from \\\"./IVRFSubscriptionV2Plus.sol\\\";\\n\\n// Interface that enables consumers of VRFCoordinatorV2Plus to be future-proof for upgrades\\n// This interface is supported by subsequent versions of VRFCoordinatorV2Plus\\ninterface IVRFCoordinatorV2Plus is IVRFSubscriptionV2Plus {\\n /**\\n * @notice Request a set of random words.\\n * @param req - a struct containing following fields for randomness request:\\n * keyHash - Corresponds to a particular oracle job which uses\\n * that key for generating the VRF proof. Different keyHash's have different gas price\\n * ceilings, so you can select a specific one to bound your maximum per request cost.\\n * subId - The ID of the VRF subscription. Must be funded\\n * with the minimum subscription balance required for the selected keyHash.\\n * requestConfirmations - How many blocks you'd like the\\n * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS\\n * for why you may want to request more. The acceptable range is\\n * [minimumRequestBlockConfirmations, 200].\\n * callbackGasLimit - How much gas you'd like to receive in your\\n * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords\\n * may be slightly less than this amount because of gas used calling the function\\n * (argument decoding etc.), so you may need to request slightly more than you expect\\n * to have inside fulfillRandomWords. The acceptable range is\\n * [0, maxGasLimit]\\n * numWords - The number of uint256 random values you'd like to receive\\n * in your fulfillRandomWords callback. Note these numbers are expanded in a\\n * secure way by the VRFCoordinator from a single random value supplied by the oracle.\\n * extraArgs - abi-encoded extra args\\n * @return requestId - A unique identifier of the request. Can be used to match\\n * a request to a response in fulfillRandomWords.\\n */\\n function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId);\\n}\\n\",\"keccak256\":\"0x7dca2a64690ddd95ee05e422e1f61e7c1d701aaf5be1390ae12e9bd144266c36\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice The IVRFMigratableConsumerV2Plus interface defines the\\n/// @notice method required to be implemented by all V2Plus consumers.\\n/// @dev This interface is designed to be used in VRFConsumerBaseV2Plus.\\ninterface IVRFMigratableConsumerV2Plus {\\n event CoordinatorSet(address vrfCoordinator);\\n\\n /// @notice Sets the VRF Coordinator address\\n /// @notice This method should only be callable by the coordinator or contract owner\\n function setCoordinator(address vrfCoordinator) external;\\n}\\n\",\"keccak256\":\"0x8be8744e3b8380dc85354cf110e8caef8f394266e79120ad675a7da835ed2a85\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice The IVRFSubscriptionV2Plus interface defines the subscription\\n/// @notice related methods implemented by the V2Plus coordinator.\\ninterface IVRFSubscriptionV2Plus {\\n /**\\n * @notice Add a consumer to a VRF subscription.\\n * @param subId - ID of the subscription\\n * @param consumer - New consumer which can use the subscription\\n */\\n function addConsumer(uint256 subId, address consumer) external;\\n\\n /**\\n * @notice Remove a consumer from a VRF subscription.\\n * @param subId - ID of the subscription\\n * @param consumer - Consumer to remove from the subscription\\n */\\n function removeConsumer(uint256 subId, address consumer) external;\\n\\n /**\\n * @notice Cancel a subscription\\n * @param subId - ID of the subscription\\n * @param to - Where to send the remaining LINK to\\n */\\n function cancelSubscription(uint256 subId, address to) external;\\n\\n /**\\n * @notice Accept subscription owner transfer.\\n * @param subId - ID of the subscription\\n * @dev will revert if original owner of subId has\\n * not requested that msg.sender become the new owner.\\n */\\n function acceptSubscriptionOwnerTransfer(uint256 subId) external;\\n\\n /**\\n * @notice Request subscription owner transfer.\\n * @param subId - ID of the subscription\\n * @param newOwner - proposed new owner of the subscription\\n */\\n function requestSubscriptionOwnerTransfer(uint256 subId, address newOwner) external;\\n\\n /**\\n * @notice Create a VRF subscription.\\n * @return subId - A unique subscription id.\\n * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.\\n * @dev Note to fund the subscription with LINK, use transferAndCall. For example\\n * @dev LINKTOKEN.transferAndCall(\\n * @dev address(COORDINATOR),\\n * @dev amount,\\n * @dev abi.encode(subId));\\n * @dev Note to fund the subscription with Native, use fundSubscriptionWithNative. Be sure\\n * @dev to send Native with the call, for example:\\n * @dev COORDINATOR.fundSubscriptionWithNative{value: amount}(subId);\\n */\\n function createSubscription() external returns (uint256 subId);\\n\\n /**\\n * @notice Get a VRF subscription.\\n * @param subId - ID of the subscription\\n * @return balance - LINK balance of the subscription in juels.\\n * @return nativeBalance - native balance of the subscription in wei.\\n * @return reqCount - Requests count of subscription.\\n * @return owner - owner of the subscription.\\n * @return consumers - list of consumer address which are able to use this subscription.\\n */\\n function getSubscription(\\n uint256 subId\\n )\\n external\\n view\\n returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers);\\n\\n /*\\n * @notice Check to see if there exists a request commitment consumers\\n * for all consumers and keyhashes for a given sub.\\n * @param subId - ID of the subscription\\n * @return true if there exists at least one unfulfilled request for the subscription, false\\n * otherwise.\\n */\\n function pendingRequestExists(uint256 subId) external view returns (bool);\\n\\n /**\\n * @notice Paginate through all active VRF subscriptions.\\n * @param startIndex index of the subscription to start from\\n * @param maxCount maximum number of subscriptions to return, 0 to return all\\n * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one\\n * @dev should consider keeping the blockheight constant to ensure a holistic picture of the contract state\\n */\\n function getActiveSubscriptionIds(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory);\\n\\n /**\\n * @notice Fund a subscription with native.\\n * @param subId - ID of the subscription\\n * @notice This method expects msg.value to be greater than or equal to 0.\\n */\\n function fundSubscriptionWithNative(uint256 subId) external payable;\\n}\\n\",\"keccak256\":\"0x85b348297ce36794e3bf97a47c001fc216bd0ee243e91514a7b395f3fcd189b0\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n// End consumer library.\\nlibrary VRFV2PlusClient {\\n // extraArgs will evolve to support new features\\n bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256(\\\"VRF ExtraArgsV1\\\"));\\n struct ExtraArgsV1 {\\n bool nativePayment;\\n }\\n\\n struct RandomWordsRequest {\\n bytes32 keyHash;\\n uint256 subId;\\n uint16 requestConfirmations;\\n uint32 callbackGasLimit;\\n uint32 numWords;\\n bytes extraArgs;\\n }\\n\\n function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {\\n return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs);\\n }\\n}\\n\",\"keccak256\":\"0x839ad7a737ef18147b518b4ec3cbaf4a49dc994db65cf8369ed4e69d169a98a6\",\"license\":\"MIT\"},\"src/rng/ChainlinkRNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport {VRFConsumerBaseV2Plus, IVRFCoordinatorV2Plus} from \\\"@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol\\\";\\nimport {VRFV2PlusClient} from \\\"@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol\\\";\\n\\nimport \\\"./RNG.sol\\\";\\n\\n/// @title Random Number Generator that uses Chainlink VRF v2.5\\n/// https://blog.chain.link/introducing-vrf-v2-5/\\ncontract ChainlinkRNG is RNG, VRFConsumerBaseV2Plus {\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n address public governor; // The address that can withdraw funds.\\n address public sortitionModule; // The address of the SortitionModule.\\n bytes32 public keyHash; // The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\\n uint256 public subscriptionId; // The unique identifier of the subscription used for funding requests.\\n uint16 public requestConfirmations; // How many confirmations the Chainlink node should wait before responding.\\n // 22 bytes remaining in slot\\n uint32 public callbackGasLimit; // Gas limit for the Chainlink callback.\\n uint256 lastRequestId; // The last request ID.\\n mapping(uint256 requestId => uint256 number) public randomNumbers; // randomNumbers[requestID] is the random number for this request id, 0 otherwise.\\n\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev Emitted when a request is sent to the VRF Coordinator\\n /// @param requestId The ID of the request\\n event RequestSent(uint256 indexed requestId);\\n\\n /// Emitted when a request has been fulfilled.\\n /// @param requestId The ID of the request\\n /// @param randomWord The random value answering the request.\\n event RequestFulfilled(uint256 indexed requestId, uint256 randomWord);\\n\\n // ************************************* //\\n // * Function Modifiers * //\\n // ************************************* //\\n\\n modifier onlyByGovernor() {\\n require(governor == msg.sender, \\\"Governor only\\\");\\n _;\\n }\\n\\n modifier onlyBySortitionModule() {\\n require(sortitionModule == msg.sender, \\\"SortitionModule only\\\");\\n _;\\n }\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor, initializing the implementation to reduce attack surface.\\n /// @param _governor The Governor of the contract.\\n /// @param _sortitionModule The address of the SortitionModule contract.\\n /// @param _vrfCoordinator The address of the VRFCoordinator contract.\\n /// @param _keyHash The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\\n /// @param _subscriptionId The unique identifier of the subscription used for funding requests.\\n /// @param _requestConfirmations How many confirmations the Chainlink node should wait before responding.\\n /// @param _callbackGasLimit The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.\\n /// @dev https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number\\n constructor(\\n address _governor,\\n address _sortitionModule,\\n address _vrfCoordinator,\\n bytes32 _keyHash,\\n uint256 _subscriptionId,\\n uint16 _requestConfirmations,\\n uint32 _callbackGasLimit\\n ) VRFConsumerBaseV2Plus(_vrfCoordinator) {\\n governor = _governor;\\n sortitionModule = _sortitionModule;\\n keyHash = _keyHash;\\n subscriptionId = _subscriptionId;\\n requestConfirmations = _requestConfirmations;\\n callbackGasLimit = _callbackGasLimit;\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n /// @dev Changes the governor of the contract.\\n /// @param _governor The new governor.\\n function changeGovernor(address _governor) external onlyByGovernor {\\n governor = _governor;\\n }\\n\\n /// @dev Changes the sortition module of the contract.\\n /// @param _sortitionModule The new sortition module.\\n function changeSortitionModule(address _sortitionModule) external onlyByGovernor {\\n sortitionModule = _sortitionModule;\\n }\\n\\n /// @dev Changes the VRF Coordinator of the contract.\\n /// @param _vrfCoordinator The new VRF Coordinator.\\n function changeVrfCoordinator(address _vrfCoordinator) external onlyByGovernor {\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n emit CoordinatorSet(_vrfCoordinator);\\n }\\n\\n /// @dev Changes the key hash of the contract.\\n /// @param _keyHash The new key hash.\\n function changeKeyHash(bytes32 _keyHash) external onlyByGovernor {\\n keyHash = _keyHash;\\n }\\n\\n /// @dev Changes the subscription ID of the contract.\\n /// @param _subscriptionId The new subscription ID.\\n function changeSubscriptionId(uint256 _subscriptionId) external onlyByGovernor {\\n subscriptionId = _subscriptionId;\\n }\\n\\n /// @dev Changes the request confirmations of the contract.\\n /// @param _requestConfirmations The new request confirmations.\\n function changeRequestConfirmations(uint16 _requestConfirmations) external onlyByGovernor {\\n requestConfirmations = _requestConfirmations;\\n }\\n\\n /// @dev Changes the callback gas limit of the contract.\\n /// @param _callbackGasLimit The new callback gas limit.\\n function changeCallbackGasLimit(uint32 _callbackGasLimit) external onlyByGovernor {\\n callbackGasLimit = _callbackGasLimit;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Request a random number. SortitionModule only.\\n function requestRandomness(uint256 /*_block*/) external override onlyBySortitionModule {\\n // Will revert if subscription is not set and funded.\\n uint256 requestId = s_vrfCoordinator.requestRandomWords(\\n VRFV2PlusClient.RandomWordsRequest({\\n keyHash: keyHash,\\n subId: subscriptionId,\\n requestConfirmations: requestConfirmations,\\n callbackGasLimit: callbackGasLimit,\\n numWords: 1,\\n extraArgs: VRFV2PlusClient._argsToBytes(\\n // Set nativePayment to true to pay for VRF requests with ETH instead of LINK\\n VRFV2PlusClient.ExtraArgsV1({nativePayment: true})\\n )\\n })\\n );\\n lastRequestId = requestId;\\n emit RequestSent(requestId);\\n }\\n\\n /// @dev Callback function called by the VRF Coordinator when the random value is generated.\\n /// @param _requestId The ID of the request.\\n /// @param _randomWords The random values answering the request.\\n function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) internal override {\\n // Access control is handled by the parent VRFCoordinator.rawFulfillRandomWords()\\n randomNumbers[_requestId] = _randomWords[0];\\n emit RequestFulfilled(_requestId, _randomWords[0]);\\n }\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @dev Return the random number.\\n /// @return randomNumber The random number or 0 if it is not ready or has not been requested.\\n function receiveRandomness(uint256 /*_block*/) external view override returns (uint256 randomNumber) {\\n randomNumber = randomNumbers[lastRequestId];\\n }\\n}\\n\",\"keccak256\":\"0xf7babff149b7892449b4346d637d1890cfaf579498d366598fff91fe1efcbfcc\",\"license\":\"MIT\"},\"src/rng/RNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\ninterface RNG {\\n /// @dev Request a random number.\\n /// @param _block Block linked to the request.\\n function requestRandomness(uint256 _block) external;\\n\\n /// @dev Receive the random number.\\n /// @param _block Block the random number is linked to.\\n /// @return randomNumber Random Number. If the number is not ready or has not been required 0 instead.\\n function receiveRandomness(uint256 _block) external returns (uint256 randomNumber);\\n}\\n\",\"keccak256\":\"0xf92e0cf768afefc5cc6ef786c263b67dd00c021aa5753213dbbc33014adb68c5\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162000f4c38038062000f4c83398101604081905262000034916200022d565b8433806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000165565b5050506001600160a01b038116620000ea5760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b03199081166001600160a01b03938416179091556003805482169983169990991790985560048054909816961695909517909555600591909155600655506007805461ffff90931665ffffffffffff19909316929092176201000063ffffffff90921691909102179055620002c5565b336001600160a01b03821603620001bf5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200022857600080fd5b919050565b600080600080600080600060e0888a0312156200024957600080fd5b620002548862000210565b9650620002646020890162000210565b9550620002746040890162000210565b9450606088015193506080880151925060a088015161ffff811681146200029a57600080fd5b60c089015190925063ffffffff81168114620002b557600080fd5b8091505092959891949750929550565b610c7780620002d56000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806379ba5097116100b8578063b0fb162f1161007c578063b0fb162f146102b9578063e4c0aaf4146102da578063e86a51cb146102ed578063f2fde38b14610300578063f50d390d14610313578063f9f5dd911461032657600080fd5b806379ba5097146102675780638da5cb5b1461026f5780638ea98117146102805780639eccacf614610293578063b0049637146102a657600080fd5b80632e1daf2f1161010a5780632e1daf2f146101f25780632f68f4821461020557806339b1e245146102185780635257cd901461022b57806361728f391461024b5780637363ae1f1461025457600080fd5b806309c1ba2e146101475780630c340a241461016357806313cf90541461018e5780631fe543e3146101b257806324f74697146101c7575b600080fd5b61015060065481565b6040519081526020015b60405180910390f35b600354610176906001600160a01b031681565b6040516001600160a01b03909116815260200161015a565b61015061019c366004610a3b565b5060085460009081526009602052604090205490565b6101c56101c0366004610a54565b610339565b005b6007546101dd9062010000900463ffffffff1681565b60405163ffffffff909116815260200161015a565b600454610176906001600160a01b031681565b6101c5610213366004610a3b565b61038e565b6101c5610226366004610a3b565b6103bd565b610150610239366004610a3b565b60096020526000908152604090205481565b61015060055481565b6101c5610262366004610a3b565b6103ec565b6101c5610547565b6000546001600160a01b0316610176565b6101c561028e366004610ad3565b6105f1565b600254610176906001600160a01b031681565b6101c56102b4366004610ad3565b6106e3565b6007546102c79061ffff1681565b60405161ffff909116815260200161015a565b6101c56102e8366004610ad3565b61072f565b6101c56102fb366004610b03565b61077b565b6101c561030e366004610ad3565b6107c9565b6101c5610321366004610b29565b6107dd565b6101c5610334366004610ad3565b61081f565b6002546001600160a01b0316331461037e5760025460405163073e64fd60e21b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b610389838383610849565b505050565b6003546001600160a01b031633146103b85760405162461bcd60e51b815260040161037590610b4d565b600555565b6003546001600160a01b031633146103e75760405162461bcd60e51b815260040161037590610b4d565b600655565b6004546001600160a01b0316331461043d5760405162461bcd60e51b8152602060048201526014602482015273536f72746974696f6e4d6f64756c65206f6e6c7960601b6044820152606401610375565b6002546040805160c081018252600554815260065460208083019190915260075461ffff81168385015262010000900463ffffffff16606083015260016080830181905283519182019093529182526000926001600160a01b031691639b1c385e919060a08201906104ae906108d2565b8152506040518263ffffffff1660e01b81526004016104cd9190610b74565b6020604051808303816000875af11580156104ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105109190610c12565b600881905560405190915081907f0cd21a41891ff04ecd9a8754bec97e2fb85d2a4e7694329d4dc364c796f23d0690600090a25050565b6001546001600160a01b0316331461059a5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610375565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331480159061061757506002546001600160a01b03163314155b15610668573361062f6000546001600160a01b031690565b60025460405163061db9c160e01b81526001600160a01b0393841660048201529183166024830152919091166044820152606401610375565b6001600160a01b03811661068f5760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be69060200160405180910390a150565b6003546001600160a01b0316331461070d5760405162461bcd60e51b815260040161037590610b4d565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107595760405162461bcd60e51b815260040161037590610b4d565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107a55760405162461bcd60e51b815260040161037590610b4d565b6007805463ffffffff909216620100000265ffffffff000019909216919091179055565b6107d1610943565b6107da81610998565b50565b6003546001600160a01b031633146108075760405162461bcd60e51b815260040161037590610b4d565b6007805461ffff191661ffff92909216919091179055565b6003546001600160a01b0316331461068f5760405162461bcd60e51b815260040161037590610b4d565b8181600081811061085c5761085c610c2b565b905060200201356009600085815260200190815260200160002081905550827f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d5838360008181106108af576108af610c2b565b905060200201356040516108c591815260200190565b60405180910390a2505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161090b91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000546001600160a01b031633146109965760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610375565b565b336001600160a01b038216036109ea5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610375565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a4d57600080fd5b5035919050565b600080600060408486031215610a6957600080fd5b83359250602084013567ffffffffffffffff80821115610a8857600080fd5b818601915086601f830112610a9c57600080fd5b813581811115610aab57600080fd5b8760208260051b8501011115610ac057600080fd5b6020830194508093505050509250925092565b600060208284031215610ae557600080fd5b81356001600160a01b0381168114610afc57600080fd5b9392505050565b600060208284031215610b1557600080fd5b813563ffffffff81168114610afc57600080fd5b600060208284031215610b3b57600080fd5b813561ffff81168114610afc57600080fd5b6020808252600d908201526c476f7665726e6f72206f6e6c7960981b604082015260600190565b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015610bed5782810184015186820161010001528301610bd0565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610c2457600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fdfea2646970667358221220b1b6124dbccf3f00c097f6ec7ed9e50782f84104bf8df5577b9728b9e27f9ed864736f6c63430008180033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101425760003560e01c806379ba5097116100b8578063b0fb162f1161007c578063b0fb162f146102b9578063e4c0aaf4146102da578063e86a51cb146102ed578063f2fde38b14610300578063f50d390d14610313578063f9f5dd911461032657600080fd5b806379ba5097146102675780638da5cb5b1461026f5780638ea98117146102805780639eccacf614610293578063b0049637146102a657600080fd5b80632e1daf2f1161010a5780632e1daf2f146101f25780632f68f4821461020557806339b1e245146102185780635257cd901461022b57806361728f391461024b5780637363ae1f1461025457600080fd5b806309c1ba2e146101475780630c340a241461016357806313cf90541461018e5780631fe543e3146101b257806324f74697146101c7575b600080fd5b61015060065481565b6040519081526020015b60405180910390f35b600354610176906001600160a01b031681565b6040516001600160a01b03909116815260200161015a565b61015061019c366004610a3b565b5060085460009081526009602052604090205490565b6101c56101c0366004610a54565b610339565b005b6007546101dd9062010000900463ffffffff1681565b60405163ffffffff909116815260200161015a565b600454610176906001600160a01b031681565b6101c5610213366004610a3b565b61038e565b6101c5610226366004610a3b565b6103bd565b610150610239366004610a3b565b60096020526000908152604090205481565b61015060055481565b6101c5610262366004610a3b565b6103ec565b6101c5610547565b6000546001600160a01b0316610176565b6101c561028e366004610ad3565b6105f1565b600254610176906001600160a01b031681565b6101c56102b4366004610ad3565b6106e3565b6007546102c79061ffff1681565b60405161ffff909116815260200161015a565b6101c56102e8366004610ad3565b61072f565b6101c56102fb366004610b03565b61077b565b6101c561030e366004610ad3565b6107c9565b6101c5610321366004610b29565b6107dd565b6101c5610334366004610ad3565b61081f565b6002546001600160a01b0316331461037e5760025460405163073e64fd60e21b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b610389838383610849565b505050565b6003546001600160a01b031633146103b85760405162461bcd60e51b815260040161037590610b4d565b600555565b6003546001600160a01b031633146103e75760405162461bcd60e51b815260040161037590610b4d565b600655565b6004546001600160a01b0316331461043d5760405162461bcd60e51b8152602060048201526014602482015273536f72746974696f6e4d6f64756c65206f6e6c7960601b6044820152606401610375565b6002546040805160c081018252600554815260065460208083019190915260075461ffff81168385015262010000900463ffffffff16606083015260016080830181905283519182019093529182526000926001600160a01b031691639b1c385e919060a08201906104ae906108d2565b8152506040518263ffffffff1660e01b81526004016104cd9190610b74565b6020604051808303816000875af11580156104ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105109190610c12565b600881905560405190915081907f0cd21a41891ff04ecd9a8754bec97e2fb85d2a4e7694329d4dc364c796f23d0690600090a25050565b6001546001600160a01b0316331461059a5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610375565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331480159061061757506002546001600160a01b03163314155b15610668573361062f6000546001600160a01b031690565b60025460405163061db9c160e01b81526001600160a01b0393841660048201529183166024830152919091166044820152606401610375565b6001600160a01b03811661068f5760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be69060200160405180910390a150565b6003546001600160a01b0316331461070d5760405162461bcd60e51b815260040161037590610b4d565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107595760405162461bcd60e51b815260040161037590610b4d565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107a55760405162461bcd60e51b815260040161037590610b4d565b6007805463ffffffff909216620100000265ffffffff000019909216919091179055565b6107d1610943565b6107da81610998565b50565b6003546001600160a01b031633146108075760405162461bcd60e51b815260040161037590610b4d565b6007805461ffff191661ffff92909216919091179055565b6003546001600160a01b0316331461068f5760405162461bcd60e51b815260040161037590610b4d565b8181600081811061085c5761085c610c2b565b905060200201356009600085815260200190815260200160002081905550827f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d5838360008181106108af576108af610c2b565b905060200201356040516108c591815260200190565b60405180910390a2505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161090b91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000546001600160a01b031633146109965760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610375565b565b336001600160a01b038216036109ea5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610375565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a4d57600080fd5b5035919050565b600080600060408486031215610a6957600080fd5b83359250602084013567ffffffffffffffff80821115610a8857600080fd5b818601915086601f830112610a9c57600080fd5b813581811115610aab57600080fd5b8760208260051b8501011115610ac057600080fd5b6020830194508093505050509250925092565b600060208284031215610ae557600080fd5b81356001600160a01b0381168114610afc57600080fd5b9392505050565b600060208284031215610b1557600080fd5b813563ffffffff81168114610afc57600080fd5b600060208284031215610b3b57600080fd5b813561ffff81168114610afc57600080fd5b6020808252600d908201526c476f7665726e6f72206f6e6c7960981b604082015260600190565b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015610bed5782810184015186820161010001528301610bd0565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610c2457600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fdfea2646970667358221220b1b6124dbccf3f00c097f6ec7ed9e50782f84104bf8df5577b9728b9e27f9ed864736f6c63430008180033", + "numDeployments": 2, + "solcInputHash": "409820253ec776b564318c3061b7e926", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_sortitionModule\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_subscriptionId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"want\",\"type\":\"address\"}],\"name\":\"OnlyCoordinatorCanFulfill\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"OnlyOwnerOrCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vrfCoordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"randomWord\",\"type\":\"uint256\"}],\"name\":\"RequestFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"RequestSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"callbackGasLimit\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"name\":\"changeCallbackGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"}],\"name\":\"changeKeyHash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"}],\"name\":\"changeRequestConfirmations\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sortitionModule\",\"type\":\"address\"}],\"name\":\"changeSortitionModule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_subscriptionId\",\"type\":\"uint256\"}],\"name\":\"changeSubscriptionId\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"changeVrfCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"keyHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastRequestId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"randomNumbers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"receiveRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"randomNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requestConfirmations\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"requestRandomness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_vrfCoordinator\",\"outputs\":[{\"internalType\":\"contract IVRFCoordinatorV2Plus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sortitionModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"subscriptionId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"RequestFulfilled(uint256,uint256)\":{\"params\":{\"randomWord\":\"The random value answering the request.\",\"requestId\":\"The ID of the request\"}},\"RequestSent(uint256)\":{\"details\":\"Emitted when a request is sent to the VRF Coordinator\",\"params\":{\"requestId\":\"The ID of the request\"}}},\"kind\":\"dev\",\"methods\":{\"changeCallbackGasLimit(uint32)\":{\"details\":\"Changes the callback gas limit of the contract.\",\"params\":{\"_callbackGasLimit\":\"The new callback gas limit.\"}},\"changeGovernor(address)\":{\"details\":\"Changes the governor of the contract.\",\"params\":{\"_governor\":\"The new governor.\"}},\"changeKeyHash(bytes32)\":{\"details\":\"Changes the key hash of the contract.\",\"params\":{\"_keyHash\":\"The new key hash.\"}},\"changeRequestConfirmations(uint16)\":{\"details\":\"Changes the request confirmations of the contract.\",\"params\":{\"_requestConfirmations\":\"The new request confirmations.\"}},\"changeSortitionModule(address)\":{\"details\":\"Changes the sortition module of the contract.\",\"params\":{\"_sortitionModule\":\"The new sortition module.\"}},\"changeSubscriptionId(uint256)\":{\"details\":\"Changes the subscription ID of the contract.\",\"params\":{\"_subscriptionId\":\"The new subscription ID.\"}},\"changeVrfCoordinator(address)\":{\"details\":\"Changes the VRF Coordinator of the contract.\",\"params\":{\"_vrfCoordinator\":\"The new VRF Coordinator.\"}},\"constructor\":{\"details\":\"Constructor, initializing the implementation to reduce attack surface.https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number\",\"params\":{\"_callbackGasLimit\":\"The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.\",\"_governor\":\"The Governor of the contract.\",\"_keyHash\":\"The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\",\"_requestConfirmations\":\"How many confirmations the Chainlink node should wait before responding.\",\"_sortitionModule\":\"The address of the SortitionModule contract.\",\"_subscriptionId\":\"The unique identifier of the subscription used for funding requests.\",\"_vrfCoordinator\":\"The address of the VRFCoordinator contract.\"}},\"receiveRandomness(uint256)\":{\"details\":\"Return the random number.\",\"returns\":{\"randomNumber\":\"The random number or 0 if it is not ready or has not been requested.\"}},\"requestRandomness(uint256)\":{\"details\":\"Request a random number. SortitionModule only.\"}},\"title\":\"Random Number Generator that uses Chainlink VRF v2.5 https://blog.chain.link/introducing-vrf-v2-5/\",\"version\":1},\"userdoc\":{\"events\":{\"RequestFulfilled(uint256,uint256)\":{\"notice\":\"Emitted when a request has been fulfilled.\"}},\"kind\":\"user\",\"methods\":{\"acceptOwnership()\":{\"notice\":\"Allows an ownership transfer to be completed by the recipient.\"},\"owner()\":{\"notice\":\"Get the current owner\"},\"setCoordinator(address)\":{\"notice\":\"Sets the VRF Coordinator addressThis method should only be callable by the coordinator or contract owner\"},\"transferOwnership(address)\":{\"notice\":\"Allows an owner to begin transferring ownership to a new address.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/rng/ChainlinkRNG.sol\":\"ChainlinkRNG\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {ConfirmedOwnerWithProposal} from \\\"./ConfirmedOwnerWithProposal.sol\\\";\\n\\n/// @title The ConfirmedOwner contract\\n/// @notice A contract with helpers for basic contract ownership.\\ncontract ConfirmedOwner is ConfirmedOwnerWithProposal {\\n constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}\\n}\\n\",\"keccak256\":\"0xdcb0e9135ddbe71ee27ba99fa06656960c66c964cf2ecb29696da1c1427d9861\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {IOwnable} from \\\"../interfaces/IOwnable.sol\\\";\\n\\n/// @title The ConfirmedOwner contract\\n/// @notice A contract with helpers for basic contract ownership.\\ncontract ConfirmedOwnerWithProposal is IOwnable {\\n address private s_owner;\\n address private s_pendingOwner;\\n\\n event OwnershipTransferRequested(address indexed from, address indexed to);\\n event OwnershipTransferred(address indexed from, address indexed to);\\n\\n constructor(address newOwner, address pendingOwner) {\\n // solhint-disable-next-line gas-custom-errors\\n require(newOwner != address(0), \\\"Cannot set owner to zero\\\");\\n\\n s_owner = newOwner;\\n if (pendingOwner != address(0)) {\\n _transferOwnership(pendingOwner);\\n }\\n }\\n\\n /// @notice Allows an owner to begin transferring ownership to a new address.\\n function transferOwnership(address to) public override onlyOwner {\\n _transferOwnership(to);\\n }\\n\\n /// @notice Allows an ownership transfer to be completed by the recipient.\\n function acceptOwnership() external override {\\n // solhint-disable-next-line gas-custom-errors\\n require(msg.sender == s_pendingOwner, \\\"Must be proposed owner\\\");\\n\\n address oldOwner = s_owner;\\n s_owner = msg.sender;\\n s_pendingOwner = address(0);\\n\\n emit OwnershipTransferred(oldOwner, msg.sender);\\n }\\n\\n /// @notice Get the current owner\\n function owner() public view override returns (address) {\\n return s_owner;\\n }\\n\\n /// @notice validate, transfer ownership, and emit relevant events\\n function _transferOwnership(address to) private {\\n // solhint-disable-next-line gas-custom-errors\\n require(to != msg.sender, \\\"Cannot transfer to self\\\");\\n\\n s_pendingOwner = to;\\n\\n emit OwnershipTransferRequested(s_owner, to);\\n }\\n\\n /// @notice validate access\\n function _validateOwnership() internal view {\\n // solhint-disable-next-line gas-custom-errors\\n require(msg.sender == s_owner, \\\"Only callable by owner\\\");\\n }\\n\\n /// @notice Reverts if called by anyone other than the contract owner.\\n modifier onlyOwner() {\\n _validateOwnership();\\n _;\\n }\\n}\\n\",\"keccak256\":\"0x2422a055657a87e98be61f8f31abb1824ec50fd0f73949f4e3c6ac877efb6da8\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IOwnable {\\n function owner() external returns (address);\\n\\n function transferOwnership(address recipient) external;\\n\\n function acceptOwnership() external;\\n}\\n\",\"keccak256\":\"0x885de72b7b4e4f1bf8ba817a3f2bcc37fd9022d342c4ce76782151c30122d767\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {IVRFCoordinatorV2Plus} from \\\"./interfaces/IVRFCoordinatorV2Plus.sol\\\";\\nimport {IVRFMigratableConsumerV2Plus} from \\\"./interfaces/IVRFMigratableConsumerV2Plus.sol\\\";\\nimport {ConfirmedOwner} from \\\"../../shared/access/ConfirmedOwner.sol\\\";\\n\\n/** ****************************************************************************\\n * @notice Interface for contracts using VRF randomness\\n * *****************************************************************************\\n * @dev PURPOSE\\n *\\n * @dev Reggie the Random Oracle (not his real job) wants to provide randomness\\n * @dev to Vera the verifier in such a way that Vera can be sure he's not\\n * @dev making his output up to suit himself. Reggie provides Vera a public key\\n * @dev to which he knows the secret key. Each time Vera provides a seed to\\n * @dev Reggie, he gives back a value which is computed completely\\n * @dev deterministically from the seed and the secret key.\\n *\\n * @dev Reggie provides a proof by which Vera can verify that the output was\\n * @dev correctly computed once Reggie tells it to her, but without that proof,\\n * @dev the output is indistinguishable to her from a uniform random sample\\n * @dev from the output space.\\n *\\n * @dev The purpose of this contract is to make it easy for unrelated contracts\\n * @dev to talk to Vera the verifier about the work Reggie is doing, to provide\\n * @dev simple access to a verifiable source of randomness. It ensures 2 things:\\n * @dev 1. The fulfillment came from the VRFCoordinatorV2Plus.\\n * @dev 2. The consumer contract implements fulfillRandomWords.\\n * *****************************************************************************\\n * @dev USAGE\\n *\\n * @dev Calling contracts must inherit from VRFConsumerBaseV2Plus, and can\\n * @dev initialize VRFConsumerBaseV2Plus's attributes in their constructor as\\n * @dev shown:\\n *\\n * @dev contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus {\\n * @dev constructor(, address _vrfCoordinator, address _subOwner)\\n * @dev VRFConsumerBaseV2Plus(_vrfCoordinator, _subOwner) public {\\n * @dev \\n * @dev }\\n * @dev }\\n *\\n * @dev The oracle will have given you an ID for the VRF keypair they have\\n * @dev committed to (let's call it keyHash). Create a subscription, fund it\\n * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface\\n * @dev subscription management functions).\\n * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,\\n * @dev callbackGasLimit, numWords, extraArgs),\\n * @dev see (IVRFCoordinatorV2Plus for a description of the arguments).\\n *\\n * @dev Once the VRFCoordinatorV2Plus has received and validated the oracle's response\\n * @dev to your request, it will call your contract's fulfillRandomWords method.\\n *\\n * @dev The randomness argument to fulfillRandomWords is a set of random words\\n * @dev generated from your requestId and the blockHash of the request.\\n *\\n * @dev If your contract could have concurrent requests open, you can use the\\n * @dev requestId returned from requestRandomWords to track which response is associated\\n * @dev with which randomness request.\\n * @dev See \\\"SECURITY CONSIDERATIONS\\\" for principles to keep in mind,\\n * @dev if your contract could have multiple requests in flight simultaneously.\\n *\\n * @dev Colliding `requestId`s are cryptographically impossible as long as seeds\\n * @dev differ.\\n *\\n * *****************************************************************************\\n * @dev SECURITY CONSIDERATIONS\\n *\\n * @dev A method with the ability to call your fulfillRandomness method directly\\n * @dev could spoof a VRF response with any random value, so it's critical that\\n * @dev it cannot be directly called by anything other than this base contract\\n * @dev (specifically, by the VRFConsumerBaseV2Plus.rawFulfillRandomness method).\\n *\\n * @dev For your users to trust that your contract's random behavior is free\\n * @dev from malicious interference, it's best if you can write it so that all\\n * @dev behaviors implied by a VRF response are executed *during* your\\n * @dev fulfillRandomness method. If your contract must store the response (or\\n * @dev anything derived from it) and use it later, you must ensure that any\\n * @dev user-significant behavior which depends on that stored value cannot be\\n * @dev manipulated by a subsequent VRF request.\\n *\\n * @dev Similarly, both miners and the VRF oracle itself have some influence\\n * @dev over the order in which VRF responses appear on the blockchain, so if\\n * @dev your contract could have multiple VRF requests in flight simultaneously,\\n * @dev you must ensure that the order in which the VRF responses arrive cannot\\n * @dev be used to manipulate your contract's user-significant behavior.\\n *\\n * @dev Since the block hash of the block which contains the requestRandomness\\n * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful\\n * @dev miner could, in principle, fork the blockchain to evict the block\\n * @dev containing the request, forcing the request to be included in a\\n * @dev different block with a different hash, and therefore a different input\\n * @dev to the VRF. However, such an attack would incur a substantial economic\\n * @dev cost. This cost scales with the number of blocks the VRF oracle waits\\n * @dev until it calls responds to a request. It is for this reason that\\n * @dev that you can signal to an oracle you'd like them to wait longer before\\n * @dev responding to the request (however this is not enforced in the contract\\n * @dev and so remains effective only in the case of unmodified oracle software).\\n */\\nabstract contract VRFConsumerBaseV2Plus is IVRFMigratableConsumerV2Plus, ConfirmedOwner {\\n error OnlyCoordinatorCanFulfill(address have, address want);\\n error OnlyOwnerOrCoordinator(address have, address owner, address coordinator);\\n error ZeroAddress();\\n\\n // s_vrfCoordinator should be used by consumers to make requests to vrfCoordinator\\n // so that coordinator reference is updated after migration\\n IVRFCoordinatorV2Plus public s_vrfCoordinator;\\n\\n /**\\n * @param _vrfCoordinator address of VRFCoordinator contract\\n */\\n constructor(address _vrfCoordinator) ConfirmedOwner(msg.sender) {\\n if (_vrfCoordinator == address(0)) {\\n revert ZeroAddress();\\n }\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n }\\n\\n /**\\n * @notice fulfillRandomness handles the VRF response. Your contract must\\n * @notice implement it. See \\\"SECURITY CONSIDERATIONS\\\" above for important\\n * @notice principles to keep in mind when implementing your fulfillRandomness\\n * @notice method.\\n *\\n * @dev VRFConsumerBaseV2Plus expects its subcontracts to have a method with this\\n * @dev signature, and will call it once it has verified the proof\\n * @dev associated with the randomness. (It is triggered via a call to\\n * @dev rawFulfillRandomness, below.)\\n *\\n * @param requestId The Id initially returned by requestRandomness\\n * @param randomWords the VRF output expanded to the requested number of words\\n */\\n // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\\n function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal virtual;\\n\\n // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF\\n // proof. rawFulfillRandomness then calls fulfillRandomness, after validating\\n // the origin of the call\\n function rawFulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) external {\\n if (msg.sender != address(s_vrfCoordinator)) {\\n revert OnlyCoordinatorCanFulfill(msg.sender, address(s_vrfCoordinator));\\n }\\n fulfillRandomWords(requestId, randomWords);\\n }\\n\\n /**\\n * @inheritdoc IVRFMigratableConsumerV2Plus\\n */\\n function setCoordinator(address _vrfCoordinator) external override onlyOwnerOrCoordinator {\\n if (_vrfCoordinator == address(0)) {\\n revert ZeroAddress();\\n }\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n\\n emit CoordinatorSet(_vrfCoordinator);\\n }\\n\\n modifier onlyOwnerOrCoordinator() {\\n if (msg.sender != owner() && msg.sender != address(s_vrfCoordinator)) {\\n revert OnlyOwnerOrCoordinator(msg.sender, owner(), address(s_vrfCoordinator));\\n }\\n _;\\n }\\n}\\n\",\"keccak256\":\"0x0c92838396c5abe72754ebeae526a0434dd53fdaf63e6b98111aebd6114cfcc2\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {VRFV2PlusClient} from \\\"../libraries/VRFV2PlusClient.sol\\\";\\nimport {IVRFSubscriptionV2Plus} from \\\"./IVRFSubscriptionV2Plus.sol\\\";\\n\\n// Interface that enables consumers of VRFCoordinatorV2Plus to be future-proof for upgrades\\n// This interface is supported by subsequent versions of VRFCoordinatorV2Plus\\ninterface IVRFCoordinatorV2Plus is IVRFSubscriptionV2Plus {\\n /**\\n * @notice Request a set of random words.\\n * @param req - a struct containing following fields for randomness request:\\n * keyHash - Corresponds to a particular oracle job which uses\\n * that key for generating the VRF proof. Different keyHash's have different gas price\\n * ceilings, so you can select a specific one to bound your maximum per request cost.\\n * subId - The ID of the VRF subscription. Must be funded\\n * with the minimum subscription balance required for the selected keyHash.\\n * requestConfirmations - How many blocks you'd like the\\n * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS\\n * for why you may want to request more. The acceptable range is\\n * [minimumRequestBlockConfirmations, 200].\\n * callbackGasLimit - How much gas you'd like to receive in your\\n * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords\\n * may be slightly less than this amount because of gas used calling the function\\n * (argument decoding etc.), so you may need to request slightly more than you expect\\n * to have inside fulfillRandomWords. The acceptable range is\\n * [0, maxGasLimit]\\n * numWords - The number of uint256 random values you'd like to receive\\n * in your fulfillRandomWords callback. Note these numbers are expanded in a\\n * secure way by the VRFCoordinator from a single random value supplied by the oracle.\\n * extraArgs - abi-encoded extra args\\n * @return requestId - A unique identifier of the request. Can be used to match\\n * a request to a response in fulfillRandomWords.\\n */\\n function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId);\\n}\\n\",\"keccak256\":\"0x7dca2a64690ddd95ee05e422e1f61e7c1d701aaf5be1390ae12e9bd144266c36\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice The IVRFMigratableConsumerV2Plus interface defines the\\n/// @notice method required to be implemented by all V2Plus consumers.\\n/// @dev This interface is designed to be used in VRFConsumerBaseV2Plus.\\ninterface IVRFMigratableConsumerV2Plus {\\n event CoordinatorSet(address vrfCoordinator);\\n\\n /// @notice Sets the VRF Coordinator address\\n /// @notice This method should only be callable by the coordinator or contract owner\\n function setCoordinator(address vrfCoordinator) external;\\n}\\n\",\"keccak256\":\"0x8be8744e3b8380dc85354cf110e8caef8f394266e79120ad675a7da835ed2a85\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice The IVRFSubscriptionV2Plus interface defines the subscription\\n/// @notice related methods implemented by the V2Plus coordinator.\\ninterface IVRFSubscriptionV2Plus {\\n /**\\n * @notice Add a consumer to a VRF subscription.\\n * @param subId - ID of the subscription\\n * @param consumer - New consumer which can use the subscription\\n */\\n function addConsumer(uint256 subId, address consumer) external;\\n\\n /**\\n * @notice Remove a consumer from a VRF subscription.\\n * @param subId - ID of the subscription\\n * @param consumer - Consumer to remove from the subscription\\n */\\n function removeConsumer(uint256 subId, address consumer) external;\\n\\n /**\\n * @notice Cancel a subscription\\n * @param subId - ID of the subscription\\n * @param to - Where to send the remaining LINK to\\n */\\n function cancelSubscription(uint256 subId, address to) external;\\n\\n /**\\n * @notice Accept subscription owner transfer.\\n * @param subId - ID of the subscription\\n * @dev will revert if original owner of subId has\\n * not requested that msg.sender become the new owner.\\n */\\n function acceptSubscriptionOwnerTransfer(uint256 subId) external;\\n\\n /**\\n * @notice Request subscription owner transfer.\\n * @param subId - ID of the subscription\\n * @param newOwner - proposed new owner of the subscription\\n */\\n function requestSubscriptionOwnerTransfer(uint256 subId, address newOwner) external;\\n\\n /**\\n * @notice Create a VRF subscription.\\n * @return subId - A unique subscription id.\\n * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.\\n * @dev Note to fund the subscription with LINK, use transferAndCall. For example\\n * @dev LINKTOKEN.transferAndCall(\\n * @dev address(COORDINATOR),\\n * @dev amount,\\n * @dev abi.encode(subId));\\n * @dev Note to fund the subscription with Native, use fundSubscriptionWithNative. Be sure\\n * @dev to send Native with the call, for example:\\n * @dev COORDINATOR.fundSubscriptionWithNative{value: amount}(subId);\\n */\\n function createSubscription() external returns (uint256 subId);\\n\\n /**\\n * @notice Get a VRF subscription.\\n * @param subId - ID of the subscription\\n * @return balance - LINK balance of the subscription in juels.\\n * @return nativeBalance - native balance of the subscription in wei.\\n * @return reqCount - Requests count of subscription.\\n * @return owner - owner of the subscription.\\n * @return consumers - list of consumer address which are able to use this subscription.\\n */\\n function getSubscription(\\n uint256 subId\\n )\\n external\\n view\\n returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers);\\n\\n /*\\n * @notice Check to see if there exists a request commitment consumers\\n * for all consumers and keyhashes for a given sub.\\n * @param subId - ID of the subscription\\n * @return true if there exists at least one unfulfilled request for the subscription, false\\n * otherwise.\\n */\\n function pendingRequestExists(uint256 subId) external view returns (bool);\\n\\n /**\\n * @notice Paginate through all active VRF subscriptions.\\n * @param startIndex index of the subscription to start from\\n * @param maxCount maximum number of subscriptions to return, 0 to return all\\n * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one\\n * @dev should consider keeping the blockheight constant to ensure a holistic picture of the contract state\\n */\\n function getActiveSubscriptionIds(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory);\\n\\n /**\\n * @notice Fund a subscription with native.\\n * @param subId - ID of the subscription\\n * @notice This method expects msg.value to be greater than or equal to 0.\\n */\\n function fundSubscriptionWithNative(uint256 subId) external payable;\\n}\\n\",\"keccak256\":\"0x85b348297ce36794e3bf97a47c001fc216bd0ee243e91514a7b395f3fcd189b0\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n// End consumer library.\\nlibrary VRFV2PlusClient {\\n // extraArgs will evolve to support new features\\n bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256(\\\"VRF ExtraArgsV1\\\"));\\n struct ExtraArgsV1 {\\n bool nativePayment;\\n }\\n\\n struct RandomWordsRequest {\\n bytes32 keyHash;\\n uint256 subId;\\n uint16 requestConfirmations;\\n uint32 callbackGasLimit;\\n uint32 numWords;\\n bytes extraArgs;\\n }\\n\\n function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {\\n return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs);\\n }\\n}\\n\",\"keccak256\":\"0x839ad7a737ef18147b518b4ec3cbaf4a49dc994db65cf8369ed4e69d169a98a6\",\"license\":\"MIT\"},\"src/rng/ChainlinkRNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport {VRFConsumerBaseV2Plus, IVRFCoordinatorV2Plus} from \\\"@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol\\\";\\nimport {VRFV2PlusClient} from \\\"@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol\\\";\\n\\nimport \\\"./RNG.sol\\\";\\n\\n/// @title Random Number Generator that uses Chainlink VRF v2.5\\n/// https://blog.chain.link/introducing-vrf-v2-5/\\ncontract ChainlinkRNG is RNG, VRFConsumerBaseV2Plus {\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n address public governor; // The address that can withdraw funds.\\n address public sortitionModule; // The address of the SortitionModule.\\n bytes32 public keyHash; // The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\\n uint256 public subscriptionId; // The unique identifier of the subscription used for funding requests.\\n uint16 public requestConfirmations; // How many confirmations the Chainlink node should wait before responding.\\n // 22 bytes remaining in slot\\n uint32 public callbackGasLimit; // Gas limit for the Chainlink callback.\\n uint256 public lastRequestId; // The last request ID.\\n mapping(uint256 requestId => uint256 number) public randomNumbers; // randomNumbers[requestID] is the random number for this request id, 0 otherwise.\\n\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev Emitted when a request is sent to the VRF Coordinator\\n /// @param requestId The ID of the request\\n event RequestSent(uint256 indexed requestId);\\n\\n /// Emitted when a request has been fulfilled.\\n /// @param requestId The ID of the request\\n /// @param randomWord The random value answering the request.\\n event RequestFulfilled(uint256 indexed requestId, uint256 randomWord);\\n\\n // ************************************* //\\n // * Function Modifiers * //\\n // ************************************* //\\n\\n modifier onlyByGovernor() {\\n require(governor == msg.sender, \\\"Governor only\\\");\\n _;\\n }\\n\\n modifier onlyBySortitionModule() {\\n require(sortitionModule == msg.sender, \\\"SortitionModule only\\\");\\n _;\\n }\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor, initializing the implementation to reduce attack surface.\\n /// @param _governor The Governor of the contract.\\n /// @param _sortitionModule The address of the SortitionModule contract.\\n /// @param _vrfCoordinator The address of the VRFCoordinator contract.\\n /// @param _keyHash The gas lane key hash value - Defines the maximum gas price you are willing to pay for a request in wei (ID of the off-chain VRF job).\\n /// @param _subscriptionId The unique identifier of the subscription used for funding requests.\\n /// @param _requestConfirmations How many confirmations the Chainlink node should wait before responding.\\n /// @param _callbackGasLimit The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.\\n /// @dev https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number\\n constructor(\\n address _governor,\\n address _sortitionModule,\\n address _vrfCoordinator,\\n bytes32 _keyHash,\\n uint256 _subscriptionId,\\n uint16 _requestConfirmations,\\n uint32 _callbackGasLimit\\n ) VRFConsumerBaseV2Plus(_vrfCoordinator) {\\n governor = _governor;\\n sortitionModule = _sortitionModule;\\n keyHash = _keyHash;\\n subscriptionId = _subscriptionId;\\n requestConfirmations = _requestConfirmations;\\n callbackGasLimit = _callbackGasLimit;\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n /// @dev Changes the governor of the contract.\\n /// @param _governor The new governor.\\n function changeGovernor(address _governor) external onlyByGovernor {\\n governor = _governor;\\n }\\n\\n /// @dev Changes the sortition module of the contract.\\n /// @param _sortitionModule The new sortition module.\\n function changeSortitionModule(address _sortitionModule) external onlyByGovernor {\\n sortitionModule = _sortitionModule;\\n }\\n\\n /// @dev Changes the VRF Coordinator of the contract.\\n /// @param _vrfCoordinator The new VRF Coordinator.\\n function changeVrfCoordinator(address _vrfCoordinator) external onlyByGovernor {\\n s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);\\n emit CoordinatorSet(_vrfCoordinator);\\n }\\n\\n /// @dev Changes the key hash of the contract.\\n /// @param _keyHash The new key hash.\\n function changeKeyHash(bytes32 _keyHash) external onlyByGovernor {\\n keyHash = _keyHash;\\n }\\n\\n /// @dev Changes the subscription ID of the contract.\\n /// @param _subscriptionId The new subscription ID.\\n function changeSubscriptionId(uint256 _subscriptionId) external onlyByGovernor {\\n subscriptionId = _subscriptionId;\\n }\\n\\n /// @dev Changes the request confirmations of the contract.\\n /// @param _requestConfirmations The new request confirmations.\\n function changeRequestConfirmations(uint16 _requestConfirmations) external onlyByGovernor {\\n requestConfirmations = _requestConfirmations;\\n }\\n\\n /// @dev Changes the callback gas limit of the contract.\\n /// @param _callbackGasLimit The new callback gas limit.\\n function changeCallbackGasLimit(uint32 _callbackGasLimit) external onlyByGovernor {\\n callbackGasLimit = _callbackGasLimit;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Request a random number. SortitionModule only.\\n function requestRandomness(uint256 /*_block*/) external override onlyBySortitionModule {\\n // Will revert if subscription is not set and funded.\\n uint256 requestId = s_vrfCoordinator.requestRandomWords(\\n VRFV2PlusClient.RandomWordsRequest({\\n keyHash: keyHash,\\n subId: subscriptionId,\\n requestConfirmations: requestConfirmations,\\n callbackGasLimit: callbackGasLimit,\\n numWords: 1,\\n extraArgs: VRFV2PlusClient._argsToBytes(\\n // Set nativePayment to true to pay for VRF requests with ETH instead of LINK\\n VRFV2PlusClient.ExtraArgsV1({nativePayment: true})\\n )\\n })\\n );\\n lastRequestId = requestId;\\n emit RequestSent(requestId);\\n }\\n\\n /// @dev Callback function called by the VRF Coordinator when the random value is generated.\\n /// @param _requestId The ID of the request.\\n /// @param _randomWords The random values answering the request.\\n function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) internal override {\\n // Access control is handled by the parent VRFCoordinator.rawFulfillRandomWords()\\n randomNumbers[_requestId] = _randomWords[0];\\n emit RequestFulfilled(_requestId, _randomWords[0]);\\n }\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @dev Return the random number.\\n /// @return randomNumber The random number or 0 if it is not ready or has not been requested.\\n function receiveRandomness(uint256 /*_block*/) external view override returns (uint256 randomNumber) {\\n randomNumber = randomNumbers[lastRequestId];\\n }\\n}\\n\",\"keccak256\":\"0xf132cbbbbb47a4f11c248fab30212a3dd3e7b20b1bc5b543ff21b6d291367dc8\",\"license\":\"MIT\"},\"src/rng/RNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\ninterface RNG {\\n /// @dev Request a random number.\\n /// @param _block Block linked to the request.\\n function requestRandomness(uint256 _block) external;\\n\\n /// @dev Receive the random number.\\n /// @param _block Block the random number is linked to.\\n /// @return randomNumber Random Number. If the number is not ready or has not been required 0 instead.\\n function receiveRandomness(uint256 _block) external returns (uint256 randomNumber);\\n}\\n\",\"keccak256\":\"0xf92e0cf768afefc5cc6ef786c263b67dd00c021aa5753213dbbc33014adb68c5\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162000f6038038062000f6083398101604081905262000034916200022d565b8433806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000165565b5050506001600160a01b038116620000ea5760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b03199081166001600160a01b03938416179091556003805482169983169990991790985560048054909816961695909517909555600591909155600655506007805461ffff90931665ffffffffffff19909316929092176201000063ffffffff90921691909102179055620002c5565b336001600160a01b03821603620001bf5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200022857600080fd5b919050565b600080600080600080600060e0888a0312156200024957600080fd5b620002548862000210565b9650620002646020890162000210565b9550620002746040890162000210565b9450606088015193506080880151925060a088015161ffff811681146200029a57600080fd5b60c089015190925063ffffffff81168114620002b557600080fd5b8091505092959891949750929550565b610c8b80620002d56000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c806379ba5097116100c3578063e4c0aaf41161007c578063e4c0aaf4146102e5578063e86a51cb146102f8578063f2fde38b1461030b578063f50d390d1461031e578063f9f5dd9114610331578063fc2a88c31461034457600080fd5b806379ba5097146102725780638da5cb5b1461027a5780638ea981171461028b5780639eccacf61461029e578063b0049637146102b1578063b0fb162f146102c457600080fd5b80632e1daf2f116101155780632e1daf2f146101fd5780632f68f4821461021057806339b1e245146102235780635257cd901461023657806361728f39146102565780637363ae1f1461025f57600080fd5b806309c1ba2e146101525780630c340a241461016e57806313cf9054146101995780631fe543e3146101bd57806324f74697146101d2575b600080fd5b61015b60065481565b6040519081526020015b60405180910390f35b600354610181906001600160a01b031681565b6040516001600160a01b039091168152602001610165565b61015b6101a7366004610a4f565b5060085460009081526009602052604090205490565b6101d06101cb366004610a68565b61034d565b005b6007546101e89062010000900463ffffffff1681565b60405163ffffffff9091168152602001610165565b600454610181906001600160a01b031681565b6101d061021e366004610a4f565b6103a2565b6101d0610231366004610a4f565b6103d1565b61015b610244366004610a4f565b60096020526000908152604090205481565b61015b60055481565b6101d061026d366004610a4f565b610400565b6101d061055b565b6000546001600160a01b0316610181565b6101d0610299366004610ae7565b610605565b600254610181906001600160a01b031681565b6101d06102bf366004610ae7565b6106f7565b6007546102d29061ffff1681565b60405161ffff9091168152602001610165565b6101d06102f3366004610ae7565b610743565b6101d0610306366004610b17565b61078f565b6101d0610319366004610ae7565b6107dd565b6101d061032c366004610b3d565b6107f1565b6101d061033f366004610ae7565b610833565b61015b60085481565b6002546001600160a01b031633146103925760025460405163073e64fd60e21b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b61039d83838361085d565b505050565b6003546001600160a01b031633146103cc5760405162461bcd60e51b815260040161038990610b61565b600555565b6003546001600160a01b031633146103fb5760405162461bcd60e51b815260040161038990610b61565b600655565b6004546001600160a01b031633146104515760405162461bcd60e51b8152602060048201526014602482015273536f72746974696f6e4d6f64756c65206f6e6c7960601b6044820152606401610389565b6002546040805160c081018252600554815260065460208083019190915260075461ffff81168385015262010000900463ffffffff16606083015260016080830181905283519182019093529182526000926001600160a01b031691639b1c385e919060a08201906104c2906108e6565b8152506040518263ffffffff1660e01b81526004016104e19190610b88565b6020604051808303816000875af1158015610500573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105249190610c26565b600881905560405190915081907f0cd21a41891ff04ecd9a8754bec97e2fb85d2a4e7694329d4dc364c796f23d0690600090a25050565b6001546001600160a01b031633146105ae5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610389565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331480159061062b57506002546001600160a01b03163314155b1561067c57336106436000546001600160a01b031690565b60025460405163061db9c160e01b81526001600160a01b0393841660048201529183166024830152919091166044820152606401610389565b6001600160a01b0381166106a35760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be69060200160405180910390a150565b6003546001600160a01b031633146107215760405162461bcd60e51b815260040161038990610b61565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b0316331461076d5760405162461bcd60e51b815260040161038990610b61565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107b95760405162461bcd60e51b815260040161038990610b61565b6007805463ffffffff909216620100000265ffffffff000019909216919091179055565b6107e5610957565b6107ee816109ac565b50565b6003546001600160a01b0316331461081b5760405162461bcd60e51b815260040161038990610b61565b6007805461ffff191661ffff92909216919091179055565b6003546001600160a01b031633146106a35760405162461bcd60e51b815260040161038990610b61565b8181600081811061087057610870610c3f565b905060200201356009600085815260200190815260200160002081905550827f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d5838360008181106108c3576108c3610c3f565b905060200201356040516108d991815260200190565b60405180910390a2505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161091f91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000546001600160a01b031633146109aa5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610389565b565b336001600160a01b038216036109fe5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610389565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a6157600080fd5b5035919050565b600080600060408486031215610a7d57600080fd5b83359250602084013567ffffffffffffffff80821115610a9c57600080fd5b818601915086601f830112610ab057600080fd5b813581811115610abf57600080fd5b8760208260051b8501011115610ad457600080fd5b6020830194508093505050509250925092565b600060208284031215610af957600080fd5b81356001600160a01b0381168114610b1057600080fd5b9392505050565b600060208284031215610b2957600080fd5b813563ffffffff81168114610b1057600080fd5b600060208284031215610b4f57600080fd5b813561ffff81168114610b1057600080fd5b6020808252600d908201526c476f7665726e6f72206f6e6c7960981b604082015260600190565b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015610c015782810184015186820161010001528301610be4565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610c3857600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fdfea26469706673582212201c20e67178fd79424f46cb830b3496516dfa70ea88c1d07b59de6b70b0f17ca764736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061014d5760003560e01c806379ba5097116100c3578063e4c0aaf41161007c578063e4c0aaf4146102e5578063e86a51cb146102f8578063f2fde38b1461030b578063f50d390d1461031e578063f9f5dd9114610331578063fc2a88c31461034457600080fd5b806379ba5097146102725780638da5cb5b1461027a5780638ea981171461028b5780639eccacf61461029e578063b0049637146102b1578063b0fb162f146102c457600080fd5b80632e1daf2f116101155780632e1daf2f146101fd5780632f68f4821461021057806339b1e245146102235780635257cd901461023657806361728f39146102565780637363ae1f1461025f57600080fd5b806309c1ba2e146101525780630c340a241461016e57806313cf9054146101995780631fe543e3146101bd57806324f74697146101d2575b600080fd5b61015b60065481565b6040519081526020015b60405180910390f35b600354610181906001600160a01b031681565b6040516001600160a01b039091168152602001610165565b61015b6101a7366004610a4f565b5060085460009081526009602052604090205490565b6101d06101cb366004610a68565b61034d565b005b6007546101e89062010000900463ffffffff1681565b60405163ffffffff9091168152602001610165565b600454610181906001600160a01b031681565b6101d061021e366004610a4f565b6103a2565b6101d0610231366004610a4f565b6103d1565b61015b610244366004610a4f565b60096020526000908152604090205481565b61015b60055481565b6101d061026d366004610a4f565b610400565b6101d061055b565b6000546001600160a01b0316610181565b6101d0610299366004610ae7565b610605565b600254610181906001600160a01b031681565b6101d06102bf366004610ae7565b6106f7565b6007546102d29061ffff1681565b60405161ffff9091168152602001610165565b6101d06102f3366004610ae7565b610743565b6101d0610306366004610b17565b61078f565b6101d0610319366004610ae7565b6107dd565b6101d061032c366004610b3d565b6107f1565b6101d061033f366004610ae7565b610833565b61015b60085481565b6002546001600160a01b031633146103925760025460405163073e64fd60e21b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b61039d83838361085d565b505050565b6003546001600160a01b031633146103cc5760405162461bcd60e51b815260040161038990610b61565b600555565b6003546001600160a01b031633146103fb5760405162461bcd60e51b815260040161038990610b61565b600655565b6004546001600160a01b031633146104515760405162461bcd60e51b8152602060048201526014602482015273536f72746974696f6e4d6f64756c65206f6e6c7960601b6044820152606401610389565b6002546040805160c081018252600554815260065460208083019190915260075461ffff81168385015262010000900463ffffffff16606083015260016080830181905283519182019093529182526000926001600160a01b031691639b1c385e919060a08201906104c2906108e6565b8152506040518263ffffffff1660e01b81526004016104e19190610b88565b6020604051808303816000875af1158015610500573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105249190610c26565b600881905560405190915081907f0cd21a41891ff04ecd9a8754bec97e2fb85d2a4e7694329d4dc364c796f23d0690600090a25050565b6001546001600160a01b031633146105ae5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610389565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b0316331480159061062b57506002546001600160a01b03163314155b1561067c57336106436000546001600160a01b031690565b60025460405163061db9c160e01b81526001600160a01b0393841660048201529183166024830152919091166044820152606401610389565b6001600160a01b0381166106a35760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be69060200160405180910390a150565b6003546001600160a01b031633146107215760405162461bcd60e51b815260040161038990610b61565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b0316331461076d5760405162461bcd60e51b815260040161038990610b61565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146107b95760405162461bcd60e51b815260040161038990610b61565b6007805463ffffffff909216620100000265ffffffff000019909216919091179055565b6107e5610957565b6107ee816109ac565b50565b6003546001600160a01b0316331461081b5760405162461bcd60e51b815260040161038990610b61565b6007805461ffff191661ffff92909216919091179055565b6003546001600160a01b031633146106a35760405162461bcd60e51b815260040161038990610b61565b8181600081811061087057610870610c3f565b905060200201356009600085815260200190815260200160002081905550827f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d5838360008181106108c3576108c3610c3f565b905060200201356040516108d991815260200190565b60405180910390a2505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161091f91511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000546001600160a01b031633146109aa5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610389565b565b336001600160a01b038216036109fe5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610389565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610a6157600080fd5b5035919050565b600080600060408486031215610a7d57600080fd5b83359250602084013567ffffffffffffffff80821115610a9c57600080fd5b818601915086601f830112610ab057600080fd5b813581811115610abf57600080fd5b8760208260051b8501011115610ad457600080fd5b6020830194508093505050509250925092565b600060208284031215610af957600080fd5b81356001600160a01b0381168114610b1057600080fd5b9392505050565b600060208284031215610b2957600080fd5b813563ffffffff81168114610b1057600080fd5b600060208284031215610b4f57600080fd5b813561ffff81168114610b1057600080fd5b6020808252600d908201526c476f7665726e6f72206f6e6c7960981b604082015260600190565b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015610c015782810184015186820161010001528301610be4565b506101009250600083828701015282601f19601f830116860101935050505092915050565b600060208284031215610c3857600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fdfea26469706673582212201c20e67178fd79424f46cb830b3496516dfa70ea88c1d07b59de6b70b0f17ca764736f6c63430008180033", "devdoc": { "events": { "RequestFulfilled(uint256,uint256)": { From a5944f535c6d75cc1f52f40ac077fbd19d25c84a Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Thu, 12 Dec 2024 14:48:46 +0000 Subject: [PATCH 09/12] fix: workaround graphql-request ESM import in keeper-bot --- contracts/scripts/keeperBot.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/scripts/keeperBot.ts b/contracts/scripts/keeperBot.ts index 356c7332e..8bf13e339 100644 --- a/contracts/scripts/keeperBot.ts +++ b/contracts/scripts/keeperBot.ts @@ -9,12 +9,12 @@ import { DisputeKitClassic, ChainlinkRNG, } from "../typechain-types"; -import request from "graphql-request"; import env from "./utils/env"; import loggerFactory from "./utils/logger"; import { toBigInt, BigNumberish, getNumber } from "ethers"; import hre = require("hardhat"); +let request: (url: string, query: string) => Promise; // Workaround graphql-request ESM import const { ethers } = hre; const MAX_DRAW_ITERATIONS = 30; const MAX_EXECUTE_ITERATIONS = 20; @@ -478,6 +478,8 @@ const sendHeartbeat = async () => { }; async function main() { + const graphqlRequest = await import("graphql-request"); // Workaround graphql-request ESM import + request = graphqlRequest.request; const { core, sortition, disputeKitClassic } = await getContracts(); const getBlockTime = async () => { From 03749f380a13de989baae9cfb7dba9d7e6e683db Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Thu, 12 Dec 2024 15:25:04 +0000 Subject: [PATCH 10/12] fix: rng deploy script --- contracts/README.md | 3 - contracts/deploy/00-chainlink-rng.ts | 2 +- .../deploy/change-sortition-module-rng.ts | 38 + .../arbitrum/ChainlinkVRFCoordinator.json | 1745 ++++++++++++++++- .../scripts/generateDeploymentsMarkdown.sh | 1 + 5 files changed, 1780 insertions(+), 9 deletions(-) create mode 100644 contracts/deploy/change-sortition-module-rng.ts diff --git a/contracts/README.md b/contracts/README.md index 93a74935c..9ce2ab2cf 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -12,7 +12,6 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments - [BlockHashRNG](https://arbiscan.io/address/0x39D123fc4cFD24EA5bB76195f9ecFE1f0DF35b0B) - [ChainlinkRNG](https://arbiscan.io/address/0x897d83a7d5F23555eFA15e1BE297d5503522cbA3) -- [ChainlinkVRFCoordinator](https://arbiscan.io/address/0xf97f4df75117a78c1A5a0DBb814Af92458539FB4) - [DisputeKitClassicNeo: proxy](https://arbiscan.io/address/0x70B464be85A547144C72485eBa2577E5D3A45421), [implementation](https://arbiscan.io/address/0xAF0325dbBFa812a574743Bb5A085266D31e3e03a) - [DisputeResolverNeo](https://arbiscan.io/address/0xb5526D022962A1fFf6eD32C93e8b714c901F4323) - [DisputeTemplateRegistry: proxy](https://arbiscan.io/address/0x0cFBaCA5C72e7Ca5fFABE768E135654fB3F2a5A2), [implementation](https://arbiscan.io/address/0x57EfD43DAfCeb6C58Df57932b2B299f46fef5c87) @@ -31,7 +30,6 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments - [BlockHashRNG](https://sepolia.arbiscan.io/address/0x0298a3EFa6Faf90865725E2b48Cf0F66e5d52754) - [ChainlinkRNG](https://sepolia.arbiscan.io/address/0xAd5cCc93429e3A977c273cEeD106Ef16A69EAf79) -- [ChainlinkVRFCoordinator](https://sepolia.arbiscan.io/address/0x5CE8D5A2BC84beb22a398CCA51996F7930313D61) - [DAI](https://sepolia.arbiscan.io/address/0xc34aeFEa232956542C5b2f2EE55fD5c378B35c03) - [DAIFaucet](https://sepolia.arbiscan.io/address/0x1Fa58B52326488D62A406E71DBaD839560e810fF) - [DisputeKitClassic: proxy](https://sepolia.arbiscan.io/address/0x0c38f115D001d3b5bBec5e8D44f78C7B61A27D94), [implementation](https://sepolia.arbiscan.io/address/0xDb0B7908C46E2Bb08459bf9b3155b9bb8F8713E1) @@ -73,7 +71,6 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments - [ArbitrableExample](https://sepolia.arbiscan.io/address/0x3Eae72F076c68F5c354C73abC33EAA291ef1b2Fa) - [BlockHashRNG](https://sepolia.arbiscan.io/address/0x56d6d65Fe202232714794B5D5e4ed9894466Ee01) - [ChainlinkRNG](https://sepolia.arbiscan.io/address/0x6c40D7F5d5bE3492fe9EF70e4eCb2BD773c12AF8) -- [ChainlinkVRFCoordinator](https://sepolia.arbiscan.io/address/0x5CE8D5A2BC84beb22a398CCA51996F7930313D61) - [DAI](https://sepolia.arbiscan.io/address/0x593e89704D285B0c3fbF157c7CF2537456CE64b5) - [DAIFaucet](https://sepolia.arbiscan.io/address/0xB5b39A1bcD2D7097A8824B3cC18Ebd2dFb0D9B5E) - [DisputeKitClassic: proxy](https://sepolia.arbiscan.io/address/0x9426F127116C3652A262AE1eA48391AC8F44D35b), [implementation](https://sepolia.arbiscan.io/address/0x692CC78F2570181FFB99297965FeAA8352ab12E8) diff --git a/contracts/deploy/00-chainlink-rng.ts b/contracts/deploy/00-chainlink-rng.ts index bc1508ed8..04cb29907 100644 --- a/contracts/deploy/00-chainlink-rng.ts +++ b/contracts/deploy/00-chainlink-rng.ts @@ -48,7 +48,7 @@ const deployRng: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { log: true, }); - const keyHash = getKeyHash({ gasPrice: 150 }); + const keyHash = getKeyHash({ gasPrice: 30 }); const subscriptionId = SUBSCRIPTION_ID[chainId]; const requestConfirmations = 200; // between 1 and 200 L2 blocks const callbackGasLimit = 100000; diff --git a/contracts/deploy/change-sortition-module-rng.ts b/contracts/deploy/change-sortition-module-rng.ts new file mode 100644 index 000000000..a9573e6be --- /dev/null +++ b/contracts/deploy/change-sortition-module-rng.ts @@ -0,0 +1,38 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HomeChains, isMainnet, isSkipped } from "./utils"; +import { ethers } from "hardhat"; +import { ChainlinkRNG, SortitionModule, SortitionModuleNeo } from "../typechain-types"; + +const task: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { + const { getNamedAccounts, getChainId } = hre; + + // fallback to hardhat node signers on local network + const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address; + const chainId = Number(await getChainId()) as unknown as HomeChains; // Checked at runtime by skip() + console.log("deploying to %s with deployer %s", HomeChains[chainId], deployer); + + const chainlinkRng = await ethers.getContract("ChainlinkRNG"); + + let sortitionModule: SortitionModule | SortitionModuleNeo; + if (isMainnet(hre.network)) { + console.log("Using SortitionModuleNeo"); + sortitionModule = await ethers.getContract("SortitionModuleNeo"); + } else { + console.log("Using SortitionModule"); + sortitionModule = await ethers.getContract("SortitionModule"); + } + + console.log(`chainlinkRng.changeSortitionModule(${sortitionModule.target})`); + await chainlinkRng.changeSortitionModule(sortitionModule.target); + + console.log(`sortitionModule.changeRandomNumberGenerator(${chainlinkRng.target}, 0)`); + await sortitionModule.changeRandomNumberGenerator(chainlinkRng.target, 0); +}; + +task.tags = ["ChangeSortitionModuleRNG"]; +task.skip = async ({ network }) => { + return isSkipped(network, !HomeChains[network.config.chainId ?? 0]); +}; + +export default task; diff --git a/contracts/deployments/arbitrum/ChainlinkVRFCoordinator.json b/contracts/deployments/arbitrum/ChainlinkVRFCoordinator.json index 6dbd1fef2..1c7b0579a 100644 --- a/contracts/deployments/arbitrum/ChainlinkVRFCoordinator.json +++ b/contracts/deployments/arbitrum/ChainlinkVRFCoordinator.json @@ -1,18 +1,1753 @@ { - "address": "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", + "address": "0x3C0Ca683b403E37668AE3DC4FB62F4B29B6f7a3e", "abi": [ { - "inputs": [], + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], "stateMutability": "nonpayable", "type": "constructor" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" }, { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "deregisterMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], "stateMutability": "payable", - "type": "receive" + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "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": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ] } diff --git a/contracts/scripts/generateDeploymentsMarkdown.sh b/contracts/scripts/generateDeploymentsMarkdown.sh index 280505f9c..6fa3c2932 100755 --- a/contracts/scripts/generateDeploymentsMarkdown.sh +++ b/contracts/scripts/generateDeploymentsMarkdown.sh @@ -9,6 +9,7 @@ IGNORED_ARTIFACTS=( "RandomizerOracle.json" "_Implementation.json" "_Proxy.json" + "ChainlinkVRFCoordinator.json" ) function generate() { #deploymentDir #explorerUrl From 83c4367119417eb16296a92c03bfbab47a473400 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Thu, 12 Dec 2024 16:24:14 +0000 Subject: [PATCH 11/12] test: added tests for concurrent requests for both chainlink and randomizer --- contracts/deploy/00-chainlink-rng.ts | 4 + .../rng/mock/ChainlinkVRFCoordinatorMock.sol | 4 +- contracts/src/rng/mock/RandomizerMock.sol | 2 +- contracts/test/arbitration/staking-neo.ts | 12 +- contracts/test/arbitration/staking.ts | 14 +-- contracts/test/integration/index.ts | 12 +- contracts/test/rng/index.ts | 103 +++++++++++++++++- 7 files changed, 130 insertions(+), 21 deletions(-) diff --git a/contracts/deploy/00-chainlink-rng.ts b/contracts/deploy/00-chainlink-rng.ts index 04cb29907..1062fe936 100644 --- a/contracts/deploy/00-chainlink-rng.ts +++ b/contracts/deploy/00-chainlink-rng.ts @@ -35,6 +35,10 @@ const deployRng: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { }; function getKeyHash({ gasPrice }: { gasPrice: keyof (typeof KEY_HASHES)[HomeChains.ARBITRUM_ONE] }): string { + const validGasPrices = Object.keys(KEY_HASHES[HomeChains.ARBITRUM_ONE]).map(Number); + if (!validGasPrices.includes(gasPrice)) { + throw new Error(`Invalid gas price ${gasPrice}. Valid values are: ${validGasPrices.join(", ")}`); + } if (chainId == HomeChains.HARDHAT) return KEY_HASHES[chainId][0]; if (chainId == HomeChains.ARBITRUM_ONE) return KEY_HASHES[chainId][gasPrice]; if (chainId == HomeChains.ARBITRUM_SEPOLIA) return KEY_HASHES[chainId][150]; diff --git a/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol b/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol index c78dc3798..b46da3b8a 100644 --- a/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol +++ b/contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol @@ -33,6 +33,7 @@ contract ChainlinkVRFCoordinatorV2Mock is IVRFCoordinatorV2Plus { // ************************************* // function fulfillRandomWords(uint256 _requestId, address _consumer, uint256[] memory _words) public { + if (_consumer == address(0)) revert("zero address consumer"); if (requests[_requestId].subId == 0) { revert("nonexistent request"); } @@ -49,9 +50,8 @@ contract ChainlinkVRFCoordinatorV2Mock is IVRFCoordinatorV2Plus { bytes4 FULFILL_RANDOM_WORDS_SELECTOR = bytes4(keccak256("rawFulfillRandomWords(uint256,uint256[])")); bytes memory callReq = abi.encodeWithSelector(FULFILL_RANDOM_WORDS_SELECTOR, _requestId, _words); - (bool success, ) = _consumer.call{gas: req.callbackGasLimit}(callReq); - delete (requests[_requestId]); + (bool success, ) = _consumer.call{gas: req.callbackGasLimit}(callReq); emit RandomWordsFulfilled(_requestId, success); } diff --git a/contracts/src/rng/mock/RandomizerMock.sol b/contracts/src/rng/mock/RandomizerMock.sol index 3bd3be6fc..5e0e15385 100644 --- a/contracts/src/rng/mock/RandomizerMock.sol +++ b/contracts/src/rng/mock/RandomizerMock.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.24; import "../RandomizerRNG.sol"; contract RandomizerMock is IRandomizer { - uint256 private id; + uint256 private id = 1; function request(uint256 callbackGasLimit) external override returns (uint256) { return id++; diff --git a/contracts/test/arbitration/staking-neo.ts b/contracts/test/arbitration/staking-neo.ts index 1104bb4dc..28834d116 100644 --- a/contracts/test/arbitration/staking-neo.ts +++ b/contracts/test/arbitration/staking-neo.ts @@ -7,6 +7,8 @@ import { KlerosCoreNeo, TestERC721, DisputeResolver, + ChainlinkRNG, + ChainlinkVRFCoordinatorV2Mock, } from "../../typechain-types"; import { expect } from "chai"; import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; @@ -41,8 +43,8 @@ describe("Staking", async () => { let pnk: PNK; let core: KlerosCoreNeo; let sortition: SortitionModuleNeo; - let rng: RandomizerRNG; - let randomizer: RandomizerMock; + let rng: ChainlinkRNG; + let vrfCoordinator: ChainlinkVRFCoordinatorV2Mock; let nft: TestERC721; let resolver: DisputeResolver; let balanceBefore: bigint; @@ -57,8 +59,8 @@ describe("Staking", async () => { pnk = (await ethers.getContract("PNK")) as PNK; core = (await ethers.getContract("KlerosCoreNeo")) as KlerosCoreNeo; sortition = (await ethers.getContract("SortitionModuleNeo")) as SortitionModuleNeo; - rng = (await ethers.getContract("RandomizerRNG")) as RandomizerRNG; - randomizer = (await ethers.getContract("RandomizerOracle")) as RandomizerMock; + rng = (await ethers.getContract("ChainlinkRNG")) as ChainlinkRNG; + vrfCoordinator = (await ethers.getContract("ChainlinkVRFCoordinator")) as ChainlinkVRFCoordinatorV2Mock; resolver = (await ethers.getContract("DisputeResolverNeo")) as DisputeResolver; nft = (await ethers.getContract("KlerosV2NeoEarlyUser")) as TestERC721; @@ -108,7 +110,7 @@ describe("Staking", async () => { await network.provider.send("evm_mine"); } - await randomizer.relay(rng.target, 0, ethers.randomBytes(32)); + await vrfCoordinator.fulfillRandomWords(1, rng.target, []); await sortition.passPhase(); // Generating -> Drawing expect(await sortition.phase()).to.be.equal(2); // Drawing diff --git a/contracts/test/arbitration/staking.ts b/contracts/test/arbitration/staking.ts index ffd534470..09af78ba3 100644 --- a/contracts/test/arbitration/staking.ts +++ b/contracts/test/arbitration/staking.ts @@ -1,5 +1,5 @@ import { ethers, getNamedAccounts, network, deployments } from "hardhat"; -import { PNK, KlerosCore, SortitionModule, RandomizerRNG, RandomizerMock } from "../../typechain-types"; +import { PNK, KlerosCore, SortitionModule, ChainlinkRNG, ChainlinkVRFCoordinatorV2Mock } from "../../typechain-types"; import { expect } from "chai"; /* eslint-disable no-unused-vars */ @@ -18,8 +18,8 @@ describe("Staking", async () => { let pnk: PNK; let core: KlerosCore; let sortition: SortitionModule; - let rng: RandomizerRNG; - let randomizer: RandomizerMock; + let rng: ChainlinkRNG; + let vrfCoordinator: ChainlinkVRFCoordinatorV2Mock; const deploy = async () => { ({ deployer } = await getNamedAccounts()); @@ -30,8 +30,8 @@ describe("Staking", async () => { pnk = (await ethers.getContract("PNK")) as PNK; core = (await ethers.getContract("KlerosCore")) as KlerosCore; sortition = (await ethers.getContract("SortitionModule")) as SortitionModule; - rng = (await ethers.getContract("RandomizerRNG")) as RandomizerRNG; - randomizer = (await ethers.getContract("RandomizerOracle")) as RandomizerMock; + rng = (await ethers.getContract("ChainlinkRNG")) as ChainlinkRNG; + vrfCoordinator = (await ethers.getContract("ChainlinkVRFCoordinator")) as ChainlinkVRFCoordinatorV2Mock; }; describe("When outside the Staking phase", async () => { @@ -63,7 +63,7 @@ describe("Staking", async () => { }; const reachStakingPhaseAfterDrawing = async () => { - await randomizer.relay(rng.target, 0, ethers.randomBytes(32)); + await vrfCoordinator.fulfillRandomWords(1, rng.target, []); await sortition.passPhase(); // Generating -> Drawing await core.draw(0, 5000); await sortition.passPhase(); // Drawing -> Staking @@ -404,7 +404,7 @@ describe("Staking", async () => { for (let index = 0; index < lookahead; index++) { await network.provider.send("evm_mine"); } - await randomizer.relay(rng.target, 0, ethers.randomBytes(32)); + await vrfCoordinator.fulfillRandomWords(1, rng.target, []); await sortition.passPhase(); // Generating -> Drawing await core.draw(0, 5000); diff --git a/contracts/test/integration/index.ts b/contracts/test/integration/index.ts index c4b008b27..d109a4f63 100644 --- a/contracts/test/integration/index.ts +++ b/contracts/test/integration/index.ts @@ -12,6 +12,8 @@ import { RandomizerRNG, RandomizerMock, SortitionModule, + ChainlinkRNG, + ChainlinkVRFCoordinatorV2Mock, } from "../../typechain-types"; /* eslint-disable no-unused-vars */ @@ -39,8 +41,8 @@ describe("Integration tests", async () => { } let deployer: string; - let rng: RandomizerRNG; - let randomizer: RandomizerMock; + let rng: ChainlinkRNG; + let vrfCoordinator: ChainlinkVRFCoordinatorV2Mock; let disputeKit: DisputeKitClassic; let pnk: PNK; let core: KlerosCore; @@ -56,8 +58,8 @@ describe("Integration tests", async () => { fallbackToGlobal: true, keepExistingDeployments: false, }); - rng = (await ethers.getContract("RandomizerRNG")) as RandomizerRNG; - randomizer = (await ethers.getContract("RandomizerOracle")) as RandomizerMock; + rng = (await ethers.getContract("ChainlinkRNG")) as ChainlinkRNG; + vrfCoordinator = (await ethers.getContract("ChainlinkVRFCoordinator")) as ChainlinkVRFCoordinatorV2Mock; disputeKit = (await ethers.getContract("DisputeKitClassic")) as DisputeKitClassic; pnk = (await ethers.getContract("PNK")) as PNK; core = (await ethers.getContract("KlerosCore")) as KlerosCore; @@ -162,7 +164,7 @@ describe("Integration tests", async () => { await mineBlocks(ethers.getNumber(await sortitionModule.rngLookahead())); // Wait for finality expect(await sortitionModule.phase()).to.equal(Phase.generating); console.log("KC phase: %d", await sortitionModule.phase()); - await randomizer.relay(rng.target, 0, ethers.randomBytes(32)); + await vrfCoordinator.fulfillRandomWords(1, rng.target, []); await sortitionModule.passPhase(); // Generating -> Drawing expect(await sortitionModule.phase()).to.equal(Phase.drawing); console.log("KC phase: %d", await sortitionModule.phase()); diff --git a/contracts/test/rng/index.ts b/contracts/test/rng/index.ts index 3a34808f2..a3e0e2621 100644 --- a/contracts/test/rng/index.ts +++ b/contracts/test/rng/index.ts @@ -1,6 +1,13 @@ import { expect } from "chai"; import { deployments, ethers, network } from "hardhat"; -import { IncrementalNG, BlockHashRNG, ChainlinkRNG, ChainlinkVRFCoordinatorV2Mock } from "../../typechain-types"; +import { + IncrementalNG, + BlockHashRNG, + ChainlinkRNG, + ChainlinkVRFCoordinatorV2Mock, + RandomizerRNG, + RandomizerMock, +} from "../../typechain-types"; const initialNg = 424242; const abiCoder = ethers.AbiCoder.defaultAbiCoder(); @@ -75,4 +82,98 @@ describe("ChainlinkRNG", async () => { const rn = await rng.receiveRandomness(0); expect(rn).to.equal(expectedRn); }); + + it("Should return only the last random number when multiple requests are made", async () => { + // First request + let tx = await rng.requestRandomness(0); + const requestId1 = 1; + await expect(tx).to.emit(rng, "RequestSent").withArgs(requestId1); + + // Second request + tx = await rng.requestRandomness(0); + const requestId2 = 2; + await expect(tx).to.emit(rng, "RequestSent").withArgs(requestId2); + + // Generate expected random numbers + const expectedRn1 = BigInt( + ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(["uint256", "uint256"], [requestId1, 0])) + ); + const expectedRn2 = BigInt( + ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(["uint256", "uint256"], [requestId2, 0])) + ); + expect(expectedRn1).to.not.equal(expectedRn2, "Random numbers should be different"); + + // Fulfill first request + tx = await vrfCoordinator.fulfillRandomWords(requestId1, rng.target, []); + await expect(tx).to.emit(rng, "RequestFulfilled").withArgs(requestId1, expectedRn1); + + // Fulfill second request + tx = await vrfCoordinator.fulfillRandomWords(requestId2, rng.target, []); + await expect(tx).to.emit(rng, "RequestFulfilled").withArgs(requestId2, expectedRn2); + + // Should return only the last random number + const rn = await rng.receiveRandomness(0); + expect(rn).to.equal(expectedRn2); + }); +}); + +describe("RandomizerRNG", async () => { + let rng: RandomizerRNG; + let randomizer: RandomizerMock; + + beforeEach("Setup", async () => { + await deployments.fixture(["RandomizerRNG"], { + fallbackToGlobal: true, + keepExistingDeployments: false, + }); + rng = (await ethers.getContract("RandomizerRNG")) as RandomizerRNG; + randomizer = (await ethers.getContract("RandomizerOracle")) as RandomizerMock; + }); + + it("Should return a non-zero random number", async () => { + const randomBytes = ethers.randomBytes(32); + const expectedRn = BigInt(ethers.hexlify(randomBytes)); + const requestId = 1; + + let tx = await rng.requestRandomness(0); + await expect(tx).to.emit(rng, "RequestSent").withArgs(requestId); + + tx = await randomizer.relay(rng.target, requestId, randomBytes); + await expect(tx).to.emit(rng, "RequestFulfilled").withArgs(requestId, expectedRn); + + const rn = await rng.receiveRandomness(0); + expect(rn).to.equal(expectedRn); + }); + + it("Should return only the last random number when multiple requests are made", async () => { + // First request + let tx = await rng.requestRandomness(0); + const requestId1 = 1; + await expect(tx).to.emit(rng, "RequestSent").withArgs(requestId1); + + // Second request + tx = await rng.requestRandomness(0); + const requestId2 = 2; + await expect(tx).to.emit(rng, "RequestSent").withArgs(requestId2); + + // Generate random bytes and expected numbers for both requests + const randomBytes1 = ethers.randomBytes(32); + const randomBytes2 = ethers.randomBytes(32); + const expectedRn1 = BigInt(ethers.hexlify(randomBytes1)); + const expectedRn2 = BigInt(ethers.hexlify(randomBytes2)); + + expect(expectedRn1).to.not.equal(expectedRn2, "Random numbers should be different"); + + // Fulfill first request + tx = await randomizer.relay(rng.target, requestId1, randomBytes1); + await expect(tx).to.emit(rng, "RequestFulfilled").withArgs(requestId1, expectedRn1); + + // Fulfill second request + tx = await randomizer.relay(rng.target, requestId2, randomBytes2); + await expect(tx).to.emit(rng, "RequestFulfilled").withArgs(requestId2, expectedRn2); + + // Should return only the last random number + const rn = await rng.receiveRandomness(0); + expect(rn).to.equal(expectedRn2); + }); }); From 9e0f05bca68ceab13924dbb822a70f91fa04dbf4 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 13 Dec 2024 19:02:22 +0000 Subject: [PATCH 12/12] chore: dependencies resolutions --- package.json | 46 +++++++++++++++++------------- yarn.lock | 79 +++++++++++++++------------------------------------- 2 files changed, 50 insertions(+), 75 deletions(-) diff --git a/package.json b/package.json index 8a52d3627..c1a21a434 100644 --- a/package.json +++ b/package.json @@ -47,25 +47,33 @@ "string_decoder": "^1.3.0" }, "resolutions": { - "async@npm^2.4.0": "^2.6.4", - "ejs@npm^2.6.1": "^3.1.7", - "ejs@npm:3.1.6": "^3.1.8", - "loader-utils@npm:^1.0.2": "^1.4.1", - "loader-utils@npm:^1.1.0": "^1.4.1", - "lodash@npm^4.17.4": "^4.17.21", - "minimist@npm^1.2.0": "^1.2.7", - "minimatch@npm:3.0.4": "^3.0.8", - "minimatch@npm:^3.0.4": "^3.0.8", - "nanoid^3.3.1": "^3.3.4", - "node-fetch": "^2.6.7", - "underscore@npm^3.0.4": "^1.12.1", - "eth-sig-util@npm:^1.4.2": "3.0.0", - "fast-xml-parser": "^4.2.5", - "@babel/traverse:^7.22.5": "^7.23.6", - "yargs-unparser@npm:1.6.0": "1.6.4", - "dompurify@npm:^2.4.0": "2.5.7", - "secp256k1@npm:^4.0.1": "4.0.4", - "ws@npm:^8.11.0": "8.18.0" + "async@npm^2.4.0": "npm:2.6.4", + "ejs@npm^2.6.1": "npm:3.1.7", + "ejs@npm:3.1.6": "npm:3.1.8", + "loader-utils@npm:^1.0.2": "npm:1.4.2", + "loader-utils@npm:^1.1.0": "npm:1.4.2", + "lodash@npm^4.17.4": "npm:4.17.21", + "minimist@npm^1.2.0": "npm:1.2.7", + "minimatch@npm:3.0.4": "npm:3.0.8", + "minimatch@npm:^3.0.4": "npm:3.0.8", + "nanoid^3.3.1": "npm:3.3.4", + "node-fetch": "npm:2.6.7", + "underscore@npm^3.0.4": "npm:1.12.1", + "eth-sig-util@npm:^1.4.2": "npm:3.0.0", + "fast-xml-parser": "npm:4.2.5", + "@babel/traverse:^7.22.5": "npm:7.23.6", + "yargs-unparser@npm:1.6.0": "npm:1.6.4", + "dompurify@npm:^2.4.0": "npm:2.5.7", + "secp256k1@npm:^4.0.1": "npm:4.0.4", + "ws@npm:^8.11.0": "npm:8.18.0", + "@openzeppelin/contracts@npm:4.5.0": "npm:4.9.6", + "@openzeppelin/contracts@npm:4.7.3": "npm:4.9.6", + "@openzeppelin/contracts@npm:4.8.3": "npm:4.9.6", + "@openzeppelin/contracts@npm:4.9.3": "npm:4.9.6", + "@openzeppelin/contracts-upgradeable@npm:4.5.2": "npm:4.9.6", + "@openzeppelin/contracts-upgradeable@npm:4.7.3": "npm:4.9.6", + "@openzeppelin/contracts-upgradeable@npm:4.8.3": "npm:4.9.6", + "@openzeppelin/contracts-upgradeable@npm:4.9.3": "npm:4.9.6" }, "scripts": { "check-prerequisites": "scripts/check-prerequisites.sh", diff --git a/yarn.lock b/yarn.lock index 73e811d00..e9dfc8be6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7494,59 +7494,17 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/contracts-upgradeable@npm:4.5.2": - version: 4.5.2 - resolution: "@openzeppelin/contracts-upgradeable@npm:4.5.2" - checksum: 10/5e246da7a44bb982a312ebf79978735712140692d46273566e490159b98b9041ca72cc08c3d05172137a389be4caad5afc001480bc5557f3d47162f4626e3723 - languageName: node - linkType: hard - -"@openzeppelin/contracts-upgradeable@npm:4.7.3": - version: 4.7.3 - resolution: "@openzeppelin/contracts-upgradeable@npm:4.7.3" - checksum: 10/7c72ffeca867478b5aa8e8c7adb3d1ce114cfdc797ed4f3cd074788cf4da25d620ffffd624ac7e9d1223eecffeea9f7b79200ff70dc464cc828c470ccd12ddf1 - languageName: node - linkType: hard - -"@openzeppelin/contracts-upgradeable@npm:4.8.3": - version: 4.8.3 - resolution: "@openzeppelin/contracts-upgradeable@npm:4.8.3" - checksum: 10/1ff70629f509221ef948da6de582fd19a6cf7deea884f0c2de1347ca5eb1f3910099f92fcaf1a70fcae982d8f95b58f48548d833e6ad708e5d7afbae1556fae8 - languageName: node - linkType: hard - -"@openzeppelin/contracts-upgradeable@npm:4.9.3": - version: 4.9.3 - resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.3" - checksum: 10/d8fd6fd9d2271fbdd3958c20769b72a241687883ecd3bea05a3969568cdcabdee9d53c21ac776a651c397507d9c22d8db0a4fb970d27bdab918979fae7285a2f - languageName: node - linkType: hard - -"@openzeppelin/contracts@npm:4.5.0": - version: 4.5.0 - resolution: "@openzeppelin/contracts@npm:4.5.0" - checksum: 10/8bfa1733732420331728cedd7f1f5f4e4ae0700b32c9e5def19b2d42dbb0b246709e8e22abd457e8269d743012ff2aed4e3f100a942f45d9507cb78d5dbd435b - languageName: node - linkType: hard - -"@openzeppelin/contracts@npm:4.7.3": - version: 4.7.3 - resolution: "@openzeppelin/contracts@npm:4.7.3" - checksum: 10/3d16ed8943938373ecc331c2ab83c3e8d0d89aed0c2a109aaa61ca6524b4c31cb5a81185c6f93ce9ee2dda685a4328fd85bd217929ae598f4be813d5d4cd1b78 - languageName: node - linkType: hard - -"@openzeppelin/contracts@npm:4.8.3": - version: 4.8.3 - resolution: "@openzeppelin/contracts@npm:4.8.3" - checksum: 10/276481d76afdc71690bd4204cdd47e6add30d183e20df57c76e5ffc481c783ca756842f3b0ac7e3e6336217dcde448cef8279fafae1176ac436ad86594c4bdc2 +"@openzeppelin/contracts-upgradeable@npm:4.9.6": + version: 4.9.6 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.6" + checksum: 10/af9057147f13b6f0e13ca69581777f615f2cce8c6c274ec00fbea906a9095cd9ca1fb70e2c1282122a9f522fd639641c180bf1ad79bb2722494aac5ae9e565bc languageName: node linkType: hard -"@openzeppelin/contracts@npm:4.9.3": - version: 4.9.3 - resolution: "@openzeppelin/contracts@npm:4.9.3" - checksum: 10/ce0a16a56a39b62d72370ac702bce1917096492442ff05de88521beda2c3f3935b93ee2b9a184614dd543a6181f2f0be10243f5a629be87aab284ade68c18320 +"@openzeppelin/contracts@npm:4.9.6": + version: 4.9.6 + resolution: "@openzeppelin/contracts@npm:4.9.6" + checksum: 10/71f45ad42e68c0559be4ba502115462a01c76fc805c08d3005c10b5550a093f1a2b00b2d7e9d6d1f331e147c50fd4ad832f71c4470ec5b34f5a2d0751cd19a47 languageName: node linkType: hard @@ -24594,7 +24552,7 @@ __metadata: languageName: node linkType: hard -"loader-utils@npm:^1.4.1": +"loader-utils@npm:1.4.2": version: 1.4.2 resolution: "loader-utils@npm:1.4.2" dependencies: @@ -26219,7 +26177,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:2 || 3, minimatch@npm:^3.0.2, minimatch@npm:^3.0.5, minimatch@npm:^3.0.8, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:2 || 3, minimatch@npm:^3.0.2, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -26228,6 +26186,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:3.0.8": + version: 3.0.8 + resolution: "minimatch@npm:3.0.8" + dependencies: + brace-expansion: "npm:^1.1.7" + checksum: 10/6df5373cb1ea79020beb6887ff5576c58cfabcfd32c5a65c2cf58f326e4ee8eae84f129e5fa50b8a4347fa1d1e583f931285c9fb3040d984bdfb5109ef6607ec + languageName: node + linkType: hard + "minimatch@npm:^10.0.0": version: 10.0.1 resolution: "minimatch@npm:10.0.1" @@ -26899,9 +26866,9 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.7": - version: 2.6.11 - resolution: "node-fetch@npm:2.6.11" +"node-fetch@npm:2.6.7": + version: 2.6.7 + resolution: "node-fetch@npm:2.6.7" dependencies: whatwg-url: "npm:^5.0.0" peerDependencies: @@ -26909,7 +26876,7 @@ __metadata: peerDependenciesMeta: encoding: optional: true - checksum: 10/de59f077d419ecb7889c2fda6c641af99ab7d4131e7a90803b68b2911c81f77483f15d515096603a6dd3dc738b53d8c28b68d47d38c7c41770c0dbf4238fa6fe + checksum: 10/4bc9245383db92c35601a798c9a992fdf38d99920ceac11e0e6512ef3014d188b3807ccb060bc6c4bdb57a145030c73f5b5fd6730f665979f9264bc43ca3afea languageName: node linkType: hard