Skip to content

Commit

Permalink
feat(RNG): add fallback + upgradability
Browse files Browse the repository at this point in the history
  • Loading branch information
unknownunknown1 committed Oct 29, 2023
1 parent acfcd1b commit 0428693
Show file tree
Hide file tree
Showing 14 changed files with 123 additions and 66 deletions.
12 changes: 8 additions & 4 deletions contracts/deploy/00-home-chain-arbitration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
const { ethers, deployments, getNamedAccounts, getChainId } = hre;
const { deploy, execute } = deployments;
const { AddressZero } = hre.ethers.constants;
const RNG_LOOKAHEAD = 20;
const RNG_FALLBACK = 150;

// fallback to hardhat node signers on local network
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
Expand Down Expand Up @@ -110,7 +110,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
const maxFreezingTime = devnet ? 600 : 1800;
const sortitionModule = await deployUpgradable(deployments, "SortitionModule", {
from: deployer,
args: [deployer, klerosCoreAddress, minStakingTime, maxFreezingTime, rng.address, RNG_LOOKAHEAD],
args: [deployer, klerosCoreAddress, minStakingTime, maxFreezingTime, rng.address, RNG_FALLBACK],
log: true,
}); // nonce (implementation), nonce+1 (proxy)

Expand Down Expand Up @@ -184,7 +184,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
)) as VRFSubscriptionManagerV2Mock;
await vrfSubscriptionManagerContract.topUpSubscription(BigNumber.from(10).pow(20)); // 100 LINK
const subscriptionId = await vrfSubscriptionManagerContract.subscriptionId();
const vrfConsumer = await deploy("VRFConsumerV2", {
const vrfConsumer = await deployUpgradable(deployments, "VRFConsumerV2", {
from: deployer,
args: [
deployer,
Expand All @@ -195,6 +195,8 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
requestConfirmations,
callbackGasLimit,
numWords,
AddressZero,
AddressZero,
],
log: true,
});
Expand All @@ -205,7 +207,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
"VRFSubscriptionManagerV2"
)) as VRFSubscriptionManagerV2;
const subscriptionId = await vrfSubscriptionManagerContract.subscriptionId();
const vrfConsumer = await deploy("VRFConsumerV2", {
const vrfConsumer = await deployUpgradable(deployments, "VRFConsumerV2", {
from: deployer,
args: [
deployer,
Expand All @@ -216,6 +218,8 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
requestConfirmations,
callbackGasLimit,
numWords,
AddressZero,
AddressZero,
],
log: true,
});
Expand Down
3 changes: 1 addition & 2 deletions contracts/deploy/00-rng.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
const { deployments, getNamedAccounts, getChainId } = hre;
const { deploy, execute } = deployments;
const { AddressZero } = hre.ethers.constants;
const RNG_LOOKAHEAD = 20;

// fallback to hardhat node signers on local network
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
Expand Down Expand Up @@ -56,7 +55,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
});

const sortitionModule = (await hre.ethers.getContract("SortitionModule")) as SortitionModule;
await sortitionModule.changeRandomNumberGenerator(rng.address, RNG_LOOKAHEAD);
await sortitionModule.changeRandomNumberGenerator(rng.address);
};

deployArbitration.tags = ["RNG"];
Expand Down
4 changes: 2 additions & 2 deletions contracts/deploy/upgrade-sortition-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ enum HomeChains {

const deployUpgradeSortitionModule: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
const { deployments, getNamedAccounts, getChainId } = hre;
const RNG_LOOKAHEAD = 20;
const RNG_FALLBACK = 150;

// fallback to hardhat node signers on local network
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
Expand All @@ -32,7 +32,7 @@ const deployUpgradeSortitionModule: DeployFunction = async (hre: HardhatRuntimeE
1800, // minStakingTime
1800, // maxFreezingTime
rng.address,
RNG_LOOKAHEAD,
RNG_FALLBACK,
],
});
} catch (err) {
Expand Down
2 changes: 0 additions & 2 deletions contracts/scripts/simulations/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,6 @@ task("simulate:to-freezing-and-generating-phase", "Pass phase from 'staking' to
if (isNetworkLocal(hre)) {
const { sortition, randomizerMock, randomizerRng } = await getContracts(hre);
const { wallet } = await getWallet(hre, walletindex);
const numberOfBlocksToMine = Number(await sortition.rngLookahead());
await mineBlocks(numberOfBlocksToMine, hre.network);
await randomizerMock.connect(wallet).relay(randomizerRng.address, 0, utils.randomBytes(32));
}
});
Expand Down
44 changes: 28 additions & 16 deletions contracts/src/arbitration/SortitionModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ contract SortitionModule is ISortitionModule, UUPSProxiable, Initializable {
uint256 public disputesWithoutJurors; // The number of disputes that have not finished drawing jurors.
RNG public rng; // The random number generator.
uint256 public randomNumber; // Random number returned by RNG.
uint256 public rngLookahead; // Minimal block distance between requesting and obtaining a random number.
uint256 public rngFallbackTimeout; // Time after which RNG fallback will be used if no random number was received.
uint256 public delayedStakeWriteIndex; // The index of the last `delayedStake` item that was written to the array. 0 index is skipped.
uint256 public delayedStakeReadIndex; // The index of the next `delayedStake` item that should be processed. Starts at 1 because 0 index is skipped.
mapping(bytes32 => SortitionSumTree) sortitionSumTrees; // The mapping trees by keys.
Expand Down Expand Up @@ -92,22 +92,22 @@ contract SortitionModule is ISortitionModule, UUPSProxiable, Initializable {
/// @param _minStakingTime Minimal time to stake
/// @param _maxDrawingTime Time after which the drawing phase can be switched
/// @param _rng The random number generator.
/// @param _rngLookahead Lookahead value for rng.
/// @param _rngFallbackTimeout RNG fallback timeout in seconds.
function initialize(
address _governor,
KlerosCore _core,
uint256 _minStakingTime,
uint256 _maxDrawingTime,
RNG _rng,
uint256 _rngLookahead
uint256 _rngFallbackTimeout
) external reinitializer(1) {
governor = _governor;
core = _core;
minStakingTime = _minStakingTime;
maxDrawingTime = _maxDrawingTime;
lastPhaseChange = block.timestamp;
rng = _rng;
rngLookahead = _rngLookahead;
rngFallbackTimeout = _rngFallbackTimeout;
delayedStakeReadIndex = 1;
}

Expand Down Expand Up @@ -135,18 +135,22 @@ contract SortitionModule is ISortitionModule, UUPSProxiable, Initializable {
maxDrawingTime = _maxDrawingTime;
}

/// @dev Changes the `_rng` and `_rngLookahead` storage variables.
/// @dev Changes the `_rng` storage variable.
/// @param _rng The new value for the `RNGenerator` storage variable.
/// @param _rngLookahead The new value for the `rngLookahead` storage variable.
function changeRandomNumberGenerator(RNG _rng, uint256 _rngLookahead) external onlyByGovernor {
function changeRandomNumberGenerator(RNG _rng) external onlyByGovernor {
rng = _rng;
rngLookahead = _rngLookahead;
if (phase == Phase.generating) {
rng.requestRandomness(block.number + rngLookahead);
rng.requestRandomness(block.number);
randomNumberRequestBlock = block.number;
}
}

/// @dev Changes the `rngFallbackTimeout` storage variable.
/// @param _rngFallbackTimeout The new value for the `rngFallbackTimeout` storage variable.
function changeRNGFallbackTimeout(uint256 _rngFallbackTimeout) external onlyByGovernor {
rngFallbackTimeout = _rngFallbackTimeout;
}

// ************************************* //
// * State Modifiers * //
// ************************************* //
Expand All @@ -158,23 +162,31 @@ contract SortitionModule is ISortitionModule, UUPSProxiable, Initializable {
"The minimum staking time has not passed yet."
);
require(disputesWithoutJurors > 0, "There are no disputes that need jurors.");
rng.requestRandomness(block.number + rngLookahead);
rng.requestRandomness(block.number);
randomNumberRequestBlock = block.number;
phase = Phase.generating;
lastPhaseChange = block.timestamp;
emit NewPhase(phase);
} else if (phase == Phase.generating) {
randomNumber = rng.receiveRandomness(randomNumberRequestBlock + rngLookahead);
require(randomNumber != 0, "Random number is not ready yet");
phase = Phase.drawing;
randomNumber = rng.receiveRandomness(randomNumberRequestBlock);
if (randomNumber == 0) {
if (block.number > randomNumberRequestBlock + rngFallbackTimeout) {
rng.receiveRandomnessFallback(block.number);
}
} else {
phase = Phase.drawing;
lastPhaseChange = block.timestamp;
emit NewPhase(phase);
}
} else if (phase == Phase.drawing) {
require(
disputesWithoutJurors == 0 || block.timestamp - lastPhaseChange >= maxDrawingTime,
"There are still disputes without jurors and the maximum drawing time has not passed yet."
);
phase = Phase.staking;
lastPhaseChange = block.timestamp;
emit NewPhase(phase);
}

lastPhaseChange = block.timestamp;
emit NewPhase(phase);
}

/// @dev Create a sortition sum tree at the specified key.
Expand Down
2 changes: 2 additions & 0 deletions contracts/src/rng/BlockhashRNG.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ contract BlockHashRNG is RNG {
}
randomNumbers[_block] = randomNumber;
}

function receiveRandomnessFallback(uint256 _block) external {}
}
2 changes: 2 additions & 0 deletions contracts/src/rng/IncrementalNG.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ contract IncrementalNG is RNG {
return number++;
}
}

function receiveRandomnessFallback(uint256 _block) external {}
}
2 changes: 2 additions & 0 deletions contracts/src/rng/RNG.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ interface RNG {
/// @param _block Block the random number is linked to.
/// @return randomNumber Random Number. If the number is not ready or has not been required 0 instead.
function receiveRandomness(uint256 _block) external returns (uint256 randomNumber);

function receiveRandomnessFallback(uint256 _block) external;
}
2 changes: 2 additions & 0 deletions contracts/src/rng/RandomizerRNG.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ contract RandomizerRNG is RNG, UUPSProxiable, Initializable {
randomNumbers[_id] = uint256(_value);
}

function receiveRandomnessFallback(uint256 _block) external {}

// ************************************* //
// * Public Views * //
// ************************************* //
Expand Down
8 changes: 5 additions & 3 deletions contracts/src/rng/VRFConsumerBaseV2.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "../proxy/Initializable.sol";

/** ****************************************************************************
* @notice Interface for contracts using VRF randomness
* *****************************************************************************
Expand Down Expand Up @@ -94,14 +96,14 @@ pragma solidity ^0.8.4;
* @dev responding to the request (however this is not enforced in the contract
* @dev and so remains effective only in the case of unmodified oracle software).
*/
abstract contract VRFConsumerBaseV2 {
abstract contract VRFConsumerBaseV2 is Initializable {
error OnlyCoordinatorCanFulfill(address have, address want);
address private immutable vrfCoordinator;
address private vrfCoordinator;

/**
* @param _vrfCoordinator address of VRFCoordinator contract
*/
constructor(address _vrfCoordinator) {
function vrfBase_init(address _vrfCoordinator) public onlyInitializing {
vrfCoordinator = _vrfCoordinator;
}

Expand Down
Loading

0 comments on commit 0428693

Please sign in to comment.