Skip to content

Commit 60232c1

Browse files
zmalatraxunknownunknown1
authored andcommitted
test(rng): add distinct tests for Randomizer & VRF
1 parent 2e8f43a commit 60232c1

File tree

4 files changed

+221
-12
lines changed

4 files changed

+221
-12
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
178178

179179
// Execute the setup transactions for using VRF and deploy the Consumer contract on Hardhat node
180180
if (vrfSubscriptionManager) {
181+
// The Sortition Module is not changed to the VRF Consumer, it must be done in the test.
181182
if (chainId === HomeChains.HARDHAT) {
182183
const vrfSubscriptionManagerContract = (await hre.ethers.getContract(
183184
"VRFSubscriptionManagerV2Mock"
@@ -200,8 +201,6 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
200201
log: true,
201202
});
202203
await vrfSubscriptionManagerContract.addConsumer(vrfConsumer.address);
203-
const sortitionModuleContract = (await hre.ethers.getContract("SortitionModule")) as SortitionModule;
204-
await sortitionModuleContract.changeRandomNumberGenerator(vrfConsumer.address, RNG_LOOKAHEAD);
205204
}
206205
}
207206
};

contracts/test/arbitration/draw.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,4 +415,64 @@ describe("Draw Benchmark", async () => {
415415

416416
await draw(stake, CHILD_COURT, expectFromDraw, unstake);
417417
});
418+
419+
it("Draw Benchmark - Chainlink VRF v2", async () => {
420+
const arbitrationCost = ONE_TENTH_ETH.mul(3);
421+
const [bridger] = await ethers.getSigners();
422+
const RNG_LOOKAHEAD = 20;
423+
424+
await sortitionModule.changeRandomNumberGenerator(vrfConsumer.address, RNG_LOOKAHEAD);
425+
426+
// Stake some jurors
427+
for (let i = 0; i < 16; i++) {
428+
const wallet = ethers.Wallet.createRandom().connect(ethers.provider);
429+
430+
await bridger.sendTransaction({
431+
to: wallet.address,
432+
value: ethers.utils.parseEther("10"),
433+
});
434+
expect(await wallet.getBalance()).to.equal(ethers.utils.parseEther("10"));
435+
436+
await pnk.transfer(wallet.address, ONE_THOUSAND_PNK.mul(10));
437+
expect(await pnk.balanceOf(wallet.address)).to.equal(ONE_THOUSAND_PNK.mul(10));
438+
439+
await pnk.connect(wallet).approve(core.address, ONE_THOUSAND_PNK.mul(10), { gasLimit: 300000 });
440+
await core.connect(wallet).setStake(1, ONE_THOUSAND_PNK.mul(10), { gasLimit: 5000000 });
441+
}
442+
443+
// Create a dispute
444+
const tx = await arbitrable.createDispute(2, "0x00", 0, {
445+
value: arbitrationCost,
446+
});
447+
const trace = await network.provider.send("debug_traceTransaction", [tx.hash]);
448+
const [disputeId] = ethers.utils.defaultAbiCoder.decode(["uint"], `0x${trace.returnValue}`);
449+
const lastBlock = await ethers.provider.getBlock(tx.blockNumber - 1);
450+
451+
// Relayer tx
452+
const tx2 = await homeGateway
453+
.connect(await ethers.getSigner(relayer))
454+
.relayCreateDispute(31337, lastBlock.hash, disputeId, 2, "0x00", arbitrable.address, {
455+
value: arbitrationCost,
456+
});
457+
458+
await network.provider.send("evm_increaseTime", [2000]); // Wait for minStakingTime
459+
await network.provider.send("evm_mine");
460+
await sortitionModule.passPhase(); // Staking -> Generating
461+
462+
const lookahead = await sortitionModule.rngLookahead();
463+
for (let index = 0; index < lookahead; index++) {
464+
await network.provider.send("evm_mine");
465+
}
466+
467+
const requestId = await vrfConsumer.lastRequestId(); // Needed as we emulate the vrfCoordinator manually
468+
await vrfCoordinator.fulfillRandomWords(requestId, vrfConsumer.address); // The callback calls sortitionModule.passPhase(); // Generating -> Drawing
469+
470+
await expect(core.draw(0, 1000, { gasLimit: 1000000 }))
471+
.to.emit(core, "Draw")
472+
.withArgs(anyValue, 0, 0, 0)
473+
.to.emit(core, "Draw")
474+
.withArgs(anyValue, 0, 0, 1)
475+
.to.emit(core, "Draw")
476+
.withArgs(anyValue, 0, 0, 2);
477+
});
418478
});

contracts/test/arbitration/unstake.ts

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ describe("Unstake juror", async () => {
4949
vrfCoordinator = (await ethers.getContract("VRFCoordinatorV2Mock")) as VRFCoordinatorV2Mock;
5050
});
5151

52-
it("Unstake inactive juror", async () => {
52+
it("Unstake inactive juror - Randomizer", async () => {
5353
const arbitrationCost = ONE_TENTH_ETH.mul(3);
5454

5555
await core.createCourt(1, false, ONE_THOUSAND_PNK, 1000, ONE_TENTH_ETH, 3, [0, 0, 0, 0], 3, [1]); // Parent - general court, Classic dispute kit
@@ -70,10 +70,52 @@ describe("Unstake juror", async () => {
7070
for (let index = 0; index < lookahead; index++) {
7171
await network.provider.send("evm_mine");
7272
}
73-
// await randomizer.relay(rng.address, 0, ethers.utils.randomBytes(32));
74-
const requestId = await vrfConsumer.lastRequestId();
75-
await vrfCoordinator.fulfillRandomWords(requestId, vrfConsumer.address);
76-
// await sortitionModule.passPhase(); // Generating -> Drawing
73+
74+
await randomizer.relay(rng.address, 0, ethers.utils.randomBytes(32));
75+
await sortitionModule.passPhase(); // Generating -> Drawing
76+
77+
await core.draw(0, 5000);
78+
79+
await core.passPeriod(0); // Evidence -> Voting
80+
await core.passPeriod(0); // Voting -> Appeal
81+
await core.passPeriod(0); // Appeal -> Execution
82+
83+
await sortitionModule.passPhase(); // Freezing -> Staking. Change so we don't deal with delayed stakes
84+
85+
expect(await core.getJurorCourtIDs(deployer)).to.be.deep.equal([BigNumber.from("1"), BigNumber.from("2")]);
86+
87+
await core.execute(0, 0, 1); // 1 iteration should unstake from both courts
88+
89+
expect(await core.getJurorCourtIDs(deployer)).to.be.deep.equal([]);
90+
});
91+
92+
it("Unstake inactive juror - Chainlink VRF v2", async () => {
93+
const arbitrationCost = ONE_TENTH_ETH.mul(3);
94+
const RNG_LOOKAHEAD = 20;
95+
96+
await sortitionModule.changeRandomNumberGenerator(vrfConsumer.address, RNG_LOOKAHEAD);
97+
98+
await core.createCourt(1, false, ONE_THOUSAND_PNK, 1000, ONE_TENTH_ETH, 3, [0, 0, 0, 0], 3, [1]); // Parent - general court, Classic dispute kit
99+
100+
await pnk.approve(core.address, ONE_THOUSAND_PNK.mul(4));
101+
await core.setStake(1, ONE_THOUSAND_PNK.mul(2));
102+
await core.setStake(2, ONE_THOUSAND_PNK.mul(2));
103+
104+
expect(await core.getJurorCourtIDs(deployer)).to.be.deep.equal([BigNumber.from("1"), BigNumber.from("2")]);
105+
106+
await core.createDispute(2, extraData, { value: arbitrationCost });
107+
108+
await network.provider.send("evm_increaseTime", [2000]); // Wait for minStakingTime
109+
await network.provider.send("evm_mine");
110+
111+
const lookahead = await sortitionModule.rngLookahead();
112+
await sortitionModule.passPhase(); // Staking -> Generating
113+
for (let index = 0; index < lookahead; index++) {
114+
await network.provider.send("evm_mine");
115+
}
116+
117+
const requestId = await vrfConsumer.lastRequestId(); // Needed as we emulate the vrfCoordinator manually
118+
await vrfCoordinator.fulfillRandomWords(requestId, vrfConsumer.address); // The callback calls sortitionModule.passPhase(); // Generating -> Drawing
77119

78120
await core.draw(0, 5000);
79121

contracts/test/integration/index.ts

Lines changed: 113 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ describe("Integration tests", async () => {
7575
sortitionModule = (await ethers.getContract("SortitionModule")) as SortitionModule;
7676
});
7777

78-
it("Resolves a dispute on the home chain with no appeal", async () => {
78+
it("Resolves a dispute on the home chain with no appeal - Randomizer", async () => {
7979
const arbitrationCost = ONE_TENTH_ETH.mul(3);
8080
const [, , relayer] = await ethers.getSigners();
8181

@@ -165,10 +165,118 @@ describe("Integration tests", async () => {
165165
await mineBlocks(await sortitionModule.rngLookahead()); // Wait for finality
166166
expect(await sortitionModule.phase()).to.equal(Phase.generating);
167167
console.log("KC phase: %d", await sortitionModule.phase());
168-
// await randomizer.relay(rng.address, 0, ethers.utils.randomBytes(32));
169-
const reqId = await vrfConsumer.lastRequestId();
170-
await vrfCoordinator.fulfillRandomWords(reqId, vrfConsumer.address);
171-
// await sortitionModule.passPhase(); // Generating -> Drawing
168+
169+
await randomizer.relay(rng.address, 0, ethers.utils.randomBytes(32));
170+
await sortitionModule.passPhase(); // Generating -> Drawing
171+
expect(await sortitionModule.phase()).to.equal(Phase.drawing);
172+
console.log("KC phase: %d", await sortitionModule.phase());
173+
174+
const tx3 = await core.draw(0, 1000);
175+
console.log("draw successful");
176+
const events3 = (await tx3.wait()).events;
177+
178+
const roundInfo = await core.getRoundInfo(0, 0);
179+
expect(roundInfo.drawnJurors).deep.equal([deployer, deployer, deployer]);
180+
expect(roundInfo.tokensAtStakePerJuror).to.equal(ONE_HUNDRED_PNK.mul(2));
181+
expect(roundInfo.totalFeesForJurors).to.equal(arbitrationCost);
182+
183+
expect((await core.disputes(0)).period).to.equal(Period.evidence);
184+
185+
await core.passPeriod(0);
186+
expect((await core.disputes(0)).period).to.equal(Period.vote);
187+
await disputeKit.connect(await ethers.getSigner(deployer)).castVote(0, [0, 1, 2], 0, 0, "");
188+
await core.passPeriod(0);
189+
190+
await network.provider.send("evm_increaseTime", [100]); // Wait for the appeal period
191+
await network.provider.send("evm_mine");
192+
193+
await core.passPeriod(0);
194+
expect((await core.disputes(0)).period).to.equal(Period.execution);
195+
expect(await core.execute(0, 0, 1000)).to.emit(core, "TokenAndETHShift");
196+
197+
const tx4 = await core.executeRuling(0, { gasLimit: 10000000, gasPrice: 5000000000 });
198+
console.log("Ruling executed on KlerosCore");
199+
expect(tx4).to.emit(core, "Ruling").withArgs(homeGateway.address, 0, 0);
200+
expect(tx4).to.emit(arbitrable, "Ruling").withArgs(foreignGateway.address, 1, 0); // The ForeignGateway starts counting disputeID from 1.
201+
});
202+
203+
it("Resolves a dispute on the home chain with no appeal - Chainlink VRF v2", async () => {
204+
const arbitrationCost = ONE_TENTH_ETH.mul(3);
205+
const [bridger, challenger, relayer] = await ethers.getSigners();
206+
const RNG_LOOKAHEAD = 20;
207+
208+
await sortitionModule.changeRandomNumberGenerator(vrfConsumer.address, RNG_LOOKAHEAD);
209+
210+
await pnk.approve(core.address, ONE_THOUSAND_PNK.mul(100));
211+
212+
await core.setStake(1, ONE_THOUSAND_PNK);
213+
await core.getJurorBalance(deployer, 1).then((result) => {
214+
expect(result.staked).to.equal(ONE_THOUSAND_PNK);
215+
expect(result.locked).to.equal(0);
216+
logJurorBalance(result);
217+
});
218+
219+
await core.setStake(1, ONE_HUNDRED_PNK.mul(5));
220+
await core.getJurorBalance(deployer, 1).then((result) => {
221+
expect(result.staked).to.equal(ONE_HUNDRED_PNK.mul(5));
222+
expect(result.locked).to.equal(0);
223+
logJurorBalance(result);
224+
});
225+
226+
await core.setStake(1, 0);
227+
await core.getJurorBalance(deployer, 1).then((result) => {
228+
expect(result.staked).to.equal(0);
229+
expect(result.locked).to.equal(0);
230+
logJurorBalance(result);
231+
});
232+
233+
await core.setStake(1, ONE_THOUSAND_PNK.mul(4));
234+
await core.getJurorBalance(deployer, 1).then((result) => {
235+
expect(result.staked).to.equal(ONE_THOUSAND_PNK.mul(4));
236+
expect(result.locked).to.equal(0);
237+
logJurorBalance(result);
238+
});
239+
const tx = await arbitrable.createDispute(2, "0x00", 0, {
240+
value: arbitrationCost,
241+
});
242+
const trace = await network.provider.send("debug_traceTransaction", [tx.hash]);
243+
const [disputeId] = ethers.utils.defaultAbiCoder.decode(["uint"], `0x${trace.returnValue}`); // get returned value from createDispute()
244+
console.log("Dispute Created");
245+
expect(tx).to.emit(foreignGateway, "DisputeCreation");
246+
expect(tx).to.emit(foreignGateway, "OutgoingDispute");
247+
console.log(`disputeId: ${disputeId}`);
248+
249+
const lastBlock = await ethers.provider.getBlock(tx.blockNumber - 1);
250+
const disputeHash = ethers.utils.solidityKeccak256(
251+
["uint", "bytes", "bytes", "uint", "uint", "bytes", "address"],
252+
[31337, lastBlock.hash, ethers.utils.toUtf8Bytes("createDispute"), disputeId, 2, "0x00", arbitrable.address]
253+
);
254+
255+
const events = (await tx.wait()).events;
256+
257+
// Relayer tx
258+
const tx2 = await homeGateway
259+
.connect(relayer)
260+
.relayCreateDispute(31337, lastBlock.hash, disputeId, 2, "0x00", arbitrable.address, {
261+
value: arbitrationCost,
262+
});
263+
expect(tx2).to.emit(homeGateway, "Dispute");
264+
const events2 = (await tx2.wait()).events;
265+
266+
await network.provider.send("evm_increaseTime", [2000]); // Wait for minStakingTime
267+
await network.provider.send("evm_mine");
268+
269+
expect(await sortitionModule.phase()).to.equal(Phase.staking);
270+
expect(await sortitionModule.disputesWithoutJurors()).to.equal(1);
271+
console.log("KC phase: %d", await sortitionModule.phase());
272+
273+
await sortitionModule.passPhase(); // Staking -> Generating
274+
await mineBlocks(await sortitionModule.rngLookahead()); // Wait for finality
275+
expect(await sortitionModule.phase()).to.equal(Phase.generating);
276+
console.log("KC phase: %d", await sortitionModule.phase());
277+
278+
const requestId = await vrfConsumer.lastRequestId(); // Needed as we emulate the vrfCoordinator manually
279+
await vrfCoordinator.fulfillRandomWords(requestId, vrfConsumer.address); // The callback calls sortitionModule.passPhase(); // Generating -> Drawing
172280
expect(await sortitionModule.phase()).to.equal(Phase.drawing);
173281
console.log("KC phase: %d", await sortitionModule.phase());
174282

0 commit comments

Comments
 (0)