Skip to content

Commit 0428693

Browse files
feat(RNG): add fallback + upgradability
1 parent acfcd1b commit 0428693

14 files changed

+123
-66
lines changed

contracts/deploy/00-home-chain-arbitration.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
4242
const { ethers, deployments, getNamedAccounts, getChainId } = hre;
4343
const { deploy, execute } = deployments;
4444
const { AddressZero } = hre.ethers.constants;
45-
const RNG_LOOKAHEAD = 20;
45+
const RNG_FALLBACK = 150;
4646

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

@@ -184,7 +184,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
184184
)) as VRFSubscriptionManagerV2Mock;
185185
await vrfSubscriptionManagerContract.topUpSubscription(BigNumber.from(10).pow(20)); // 100 LINK
186186
const subscriptionId = await vrfSubscriptionManagerContract.subscriptionId();
187-
const vrfConsumer = await deploy("VRFConsumerV2", {
187+
const vrfConsumer = await deployUpgradable(deployments, "VRFConsumerV2", {
188188
from: deployer,
189189
args: [
190190
deployer,
@@ -195,6 +195,8 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
195195
requestConfirmations,
196196
callbackGasLimit,
197197
numWords,
198+
AddressZero,
199+
AddressZero,
198200
],
199201
log: true,
200202
});
@@ -205,7 +207,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
205207
"VRFSubscriptionManagerV2"
206208
)) as VRFSubscriptionManagerV2;
207209
const subscriptionId = await vrfSubscriptionManagerContract.subscriptionId();
208-
const vrfConsumer = await deploy("VRFConsumerV2", {
210+
const vrfConsumer = await deployUpgradable(deployments, "VRFConsumerV2", {
209211
from: deployer,
210212
args: [
211213
deployer,
@@ -216,6 +218,8 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
216218
requestConfirmations,
217219
callbackGasLimit,
218220
numWords,
221+
AddressZero,
222+
AddressZero,
219223
],
220224
log: true,
221225
});

contracts/deploy/00-rng.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
1818
const { deployments, getNamedAccounts, getChainId } = hre;
1919
const { deploy, execute } = deployments;
2020
const { AddressZero } = hre.ethers.constants;
21-
const RNG_LOOKAHEAD = 20;
2221

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

5857
const sortitionModule = (await hre.ethers.getContract("SortitionModule")) as SortitionModule;
59-
await sortitionModule.changeRandomNumberGenerator(rng.address, RNG_LOOKAHEAD);
58+
await sortitionModule.changeRandomNumberGenerator(rng.address);
6059
};
6160

6261
deployArbitration.tags = ["RNG"];

contracts/deploy/upgrade-sortition-module.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ enum HomeChains {
1111

1212
const deployUpgradeSortitionModule: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
1313
const { deployments, getNamedAccounts, getChainId } = hre;
14-
const RNG_LOOKAHEAD = 20;
14+
const RNG_FALLBACK = 150;
1515

1616
// fallback to hardhat node signers on local network
1717
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
@@ -32,7 +32,7 @@ const deployUpgradeSortitionModule: DeployFunction = async (hre: HardhatRuntimeE
3232
1800, // minStakingTime
3333
1800, // maxFreezingTime
3434
rng.address,
35-
RNG_LOOKAHEAD,
35+
RNG_FALLBACK,
3636
],
3737
});
3838
} catch (err) {

contracts/scripts/simulations/tasks.ts

-2
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,6 @@ task("simulate:to-freezing-and-generating-phase", "Pass phase from 'staking' to
406406
if (isNetworkLocal(hre)) {
407407
const { sortition, randomizerMock, randomizerRng } = await getContracts(hre);
408408
const { wallet } = await getWallet(hre, walletindex);
409-
const numberOfBlocksToMine = Number(await sortition.rngLookahead());
410-
await mineBlocks(numberOfBlocksToMine, hre.network);
411409
await randomizerMock.connect(wallet).relay(randomizerRng.address, 0, utils.randomBytes(32));
412410
}
413411
});

contracts/src/arbitration/SortitionModule.sol

+28-16
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ contract SortitionModule is ISortitionModule, UUPSProxiable, Initializable {
5858
uint256 public disputesWithoutJurors; // The number of disputes that have not finished drawing jurors.
5959
RNG public rng; // The random number generator.
6060
uint256 public randomNumber; // Random number returned by RNG.
61-
uint256 public rngLookahead; // Minimal block distance between requesting and obtaining a random number.
61+
uint256 public rngFallbackTimeout; // Time after which RNG fallback will be used if no random number was received.
6262
uint256 public delayedStakeWriteIndex; // The index of the last `delayedStake` item that was written to the array. 0 index is skipped.
6363
uint256 public delayedStakeReadIndex; // The index of the next `delayedStake` item that should be processed. Starts at 1 because 0 index is skipped.
6464
mapping(bytes32 => SortitionSumTree) sortitionSumTrees; // The mapping trees by keys.
@@ -92,22 +92,22 @@ contract SortitionModule is ISortitionModule, UUPSProxiable, Initializable {
9292
/// @param _minStakingTime Minimal time to stake
9393
/// @param _maxDrawingTime Time after which the drawing phase can be switched
9494
/// @param _rng The random number generator.
95-
/// @param _rngLookahead Lookahead value for rng.
95+
/// @param _rngFallbackTimeout RNG fallback timeout in seconds.
9696
function initialize(
9797
address _governor,
9898
KlerosCore _core,
9999
uint256 _minStakingTime,
100100
uint256 _maxDrawingTime,
101101
RNG _rng,
102-
uint256 _rngLookahead
102+
uint256 _rngFallbackTimeout
103103
) external reinitializer(1) {
104104
governor = _governor;
105105
core = _core;
106106
minStakingTime = _minStakingTime;
107107
maxDrawingTime = _maxDrawingTime;
108108
lastPhaseChange = block.timestamp;
109109
rng = _rng;
110-
rngLookahead = _rngLookahead;
110+
rngFallbackTimeout = _rngFallbackTimeout;
111111
delayedStakeReadIndex = 1;
112112
}
113113

@@ -135,18 +135,22 @@ contract SortitionModule is ISortitionModule, UUPSProxiable, Initializable {
135135
maxDrawingTime = _maxDrawingTime;
136136
}
137137

138-
/// @dev Changes the `_rng` and `_rngLookahead` storage variables.
138+
/// @dev Changes the `_rng` storage variable.
139139
/// @param _rng The new value for the `RNGenerator` storage variable.
140-
/// @param _rngLookahead The new value for the `rngLookahead` storage variable.
141-
function changeRandomNumberGenerator(RNG _rng, uint256 _rngLookahead) external onlyByGovernor {
140+
function changeRandomNumberGenerator(RNG _rng) external onlyByGovernor {
142141
rng = _rng;
143-
rngLookahead = _rngLookahead;
144142
if (phase == Phase.generating) {
145-
rng.requestRandomness(block.number + rngLookahead);
143+
rng.requestRandomness(block.number);
146144
randomNumberRequestBlock = block.number;
147145
}
148146
}
149147

148+
/// @dev Changes the `rngFallbackTimeout` storage variable.
149+
/// @param _rngFallbackTimeout The new value for the `rngFallbackTimeout` storage variable.
150+
function changeRNGFallbackTimeout(uint256 _rngFallbackTimeout) external onlyByGovernor {
151+
rngFallbackTimeout = _rngFallbackTimeout;
152+
}
153+
150154
// ************************************* //
151155
// * State Modifiers * //
152156
// ************************************* //
@@ -158,23 +162,31 @@ contract SortitionModule is ISortitionModule, UUPSProxiable, Initializable {
158162
"The minimum staking time has not passed yet."
159163
);
160164
require(disputesWithoutJurors > 0, "There are no disputes that need jurors.");
161-
rng.requestRandomness(block.number + rngLookahead);
165+
rng.requestRandomness(block.number);
162166
randomNumberRequestBlock = block.number;
163167
phase = Phase.generating;
168+
lastPhaseChange = block.timestamp;
169+
emit NewPhase(phase);
164170
} else if (phase == Phase.generating) {
165-
randomNumber = rng.receiveRandomness(randomNumberRequestBlock + rngLookahead);
166-
require(randomNumber != 0, "Random number is not ready yet");
167-
phase = Phase.drawing;
171+
randomNumber = rng.receiveRandomness(randomNumberRequestBlock);
172+
if (randomNumber == 0) {
173+
if (block.number > randomNumberRequestBlock + rngFallbackTimeout) {
174+
rng.receiveRandomnessFallback(block.number);
175+
}
176+
} else {
177+
phase = Phase.drawing;
178+
lastPhaseChange = block.timestamp;
179+
emit NewPhase(phase);
180+
}
168181
} else if (phase == Phase.drawing) {
169182
require(
170183
disputesWithoutJurors == 0 || block.timestamp - lastPhaseChange >= maxDrawingTime,
171184
"There are still disputes without jurors and the maximum drawing time has not passed yet."
172185
);
173186
phase = Phase.staking;
187+
lastPhaseChange = block.timestamp;
188+
emit NewPhase(phase);
174189
}
175-
176-
lastPhaseChange = block.timestamp;
177-
emit NewPhase(phase);
178190
}
179191

180192
/// @dev Create a sortition sum tree at the specified key.

contracts/src/rng/BlockhashRNG.sol

+2
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,6 @@ contract BlockHashRNG is RNG {
4141
}
4242
randomNumbers[_block] = randomNumber;
4343
}
44+
45+
function receiveRandomnessFallback(uint256 _block) external {}
4446
}

contracts/src/rng/IncrementalNG.sol

+2
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,6 @@ contract IncrementalNG is RNG {
2828
return number++;
2929
}
3030
}
31+
32+
function receiveRandomnessFallback(uint256 _block) external {}
3133
}

contracts/src/rng/RNG.sol

+2
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ interface RNG {
1111
/// @param _block Block the random number is linked to.
1212
/// @return randomNumber Random Number. If the number is not ready or has not been required 0 instead.
1313
function receiveRandomness(uint256 _block) external returns (uint256 randomNumber);
14+
15+
function receiveRandomnessFallback(uint256 _block) external;
1416
}

contracts/src/rng/RandomizerRNG.sol

+2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ contract RandomizerRNG is RNG, UUPSProxiable, Initializable {
9999
randomNumbers[_id] = uint256(_value);
100100
}
101101

102+
function receiveRandomnessFallback(uint256 _block) external {}
103+
102104
// ************************************* //
103105
// * Public Views * //
104106
// ************************************* //

contracts/src/rng/VRFConsumerBaseV2.sol

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.4;
33

4+
import "../proxy/Initializable.sol";
5+
46
/** ****************************************************************************
57
* @notice Interface for contracts using VRF randomness
68
* *****************************************************************************
@@ -94,14 +96,14 @@ pragma solidity ^0.8.4;
9496
* @dev responding to the request (however this is not enforced in the contract
9597
* @dev and so remains effective only in the case of unmodified oracle software).
9698
*/
97-
abstract contract VRFConsumerBaseV2 {
99+
abstract contract VRFConsumerBaseV2 is Initializable {
98100
error OnlyCoordinatorCanFulfill(address have, address want);
99-
address private immutable vrfCoordinator;
101+
address private vrfCoordinator;
100102

101103
/**
102104
* @param _vrfCoordinator address of VRFCoordinator contract
103105
*/
104-
constructor(address _vrfCoordinator) {
106+
function vrfBase_init(address _vrfCoordinator) public onlyInitializing {
105107
vrfCoordinator = _vrfCoordinator;
106108
}
107109

0 commit comments

Comments
 (0)