Skip to content

Commit cd4a3df

Browse files
committed
test(DisputeKitPlurality): added basic test, work in progress
1 parent 6a2490e commit cd4a3df

File tree

6 files changed

+152
-20
lines changed

6 files changed

+152
-20
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
## 0.1.0 (2021-12-18)
1+
## 0.1.0 (2021-12-28)
22

33
- feat: add arbitrum L1 bridge and dependencies ([b412772](https://github.com/kleros/kleros-v2/commit/b412772))
44
- feat: add arbitrum L2 bridge ([457b060](https://github.com/kleros/kleros-v2/commit/457b060))
55
- feat: dispute kit in progress ([95b8ada](https://github.com/kleros/kleros-v2/commit/95b8ada))
66
- feat: modern toolchain setup and simple RNG smart contracts ([17f6a76](https://github.com/kleros/kleros-v2/commit/17f6a76))
77
- feat(Arbitration): standard update ([ed930de](https://github.com/kleros/kleros-v2/commit/ed930de))
8+
- feat(DisputeKitPlurality): dispute creation ([6a2490e](https://github.com/kleros/kleros-v2/commit/6a2490e))
89
- feat(DisputeKitPlurality): split the responsibility of drawing jurors between Core and Dispute Kit ([f339e2b](https://github.com/kleros/kleros-v2/commit/f339e2b))
910
- refactor: add arbitrator data index getter ([47a1623](https://github.com/kleros/kleros-v2/commit/47a1623))
1011
- refactor: add evidence contracts ([09a34f3](https://github.com/kleros/kleros-v2/commit/09a34f3))

contracts/hardhat.config.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import "@nomiclabs/hardhat-waffle";
66
import "@typechain/hardhat";
77
import "hardhat-gas-reporter";
88
import "solidity-coverage";
9-
import "hardhat-deploy"
10-
import "hardhat-deploy-ethers"
9+
import "hardhat-deploy";
10+
import "hardhat-deploy-ethers";
11+
import "hardhat-watcher";
1112

1213
dotenv.config();
1314

@@ -43,6 +44,18 @@ const config: HardhatUserConfig = {
4344
saveDeployments: false,
4445
tags: ["test", "local"],
4546
},
47+
mainnetFork: {
48+
url: `http://127.0.0.1:8545`,
49+
chainId: 1,
50+
forking: {
51+
url: `https://mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`,
52+
},
53+
accounts: process.env.MAINNET_PRIVATE_KEY !== undefined ? [process.env.MAINNET_PRIVATE_KEY] : [],
54+
live: false,
55+
saveDeployments: false,
56+
tags: ["test", "local"],
57+
},
58+
4659
// Home chain ---------------------------------------------------------------------------------
4760
arbitrumRinkeby: {
4861
chainId: 421611,
@@ -101,6 +114,20 @@ const config: HardhatUserConfig = {
101114
etherscan: {
102115
apiKey: process.env.ETHERSCAN_API_KEY,
103116
},
117+
watcher: {
118+
compilation: {
119+
tasks: ["compile"],
120+
files: ["./contracts"],
121+
verbose: true,
122+
},
123+
testArbitration: {
124+
tasks: [
125+
{ command: "compile", params: { quiet: true } },
126+
{ command: "test", params: { noCompile: true, testFiles: ["./test/arbitration/index.ts"] } },
127+
],
128+
files: ["./test/**/*", "./src/**/*"],
129+
},
130+
},
104131
};
105132

106133
export default config;

contracts/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"build": "hardhat compile",
1515
"clean": "hardhat clean",
1616
"deploy": "hardhat deploy",
17-
"test": "hardhat test"
17+
"test": "hardhat test",
18+
"watch": "hardhat watch"
1819
},
1920
"devDependencies": {
2021
"@nomiclabs/hardhat-ethers": "^2.0.2",
@@ -36,6 +37,7 @@
3637
"hardhat-deploy": "^0.9.6",
3738
"hardhat-deploy-ethers": "^0.3.0-beta.11",
3839
"hardhat-gas-reporter": "^1.0.4",
40+
"hardhat-watcher": "^2.1.1",
3941
"mocha": "^9.1.3",
4042
"solhint": "^3.3.6",
4143
"solidity-coverage": "^0.7.17",

contracts/src/arbitration/DisputeKitPlurality.sol

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ contract DisputeKitPlurality is AbstractDisputeKit {
8484
Dispute[] public disputes; // Stores the dispute info. disputes[disputeID].
8585
mapping(uint256 => Round[]) public disputeIDtoRounds; // Maps dispute IDs to Round array that contains the info about crowdfunding.
8686

87-
8887
constructor(MockKlerosCore _core, RNG _rng) {
8988
core = _core;
9089
rng = _rng;
@@ -120,9 +119,6 @@ contract DisputeKitPlurality is AbstractDisputeKit {
120119
// uint feeForJuror: paid per juror
121120
// uint jurorsForCourtJump: evaluated by the appeal logic
122121

123-
// NOTE: the interface should work also for "1 human 1 vote"
124-
125-
126122
Dispute storage dispute = disputes.push();
127123
dispute.arbitratorExtraData = _extraData;
128124
dispute.choices = _choices;
@@ -141,7 +137,19 @@ contract DisputeKitPlurality is AbstractDisputeKit {
141137
dispute.penaltiesForRound.push(0);
142138
dispute.ruling = 0;
143139

144-
disputeIDtoRounds[_disputeID].push();
140+
disputeIDtoRounds[_disputeID].push();
141+
}
142+
143+
function getVotes(uint _disputeID) public view returns(Vote[][] memory) {
144+
return disputes[_disputeID].votes;
145+
}
146+
147+
function getVotesLength(uint _disputeID) public view returns(uint, uint) {
148+
return (disputes[_disputeID].votes.length, disputes[_disputeID].votes[0].length);
149+
}
150+
151+
function getVoteCounter(uint _disputeID) public view returns(bool) {
152+
return disputes[_disputeID].voteCounters[disputes[_disputeID].voteCounters.length - 1].tied;
145153
}
146154

147155
/**
@@ -165,10 +173,7 @@ contract DisputeKitPlurality is AbstractDisputeKit {
165173
for (uint256 i = 0; i < _iterations; i++) {
166174
uint256 treeIndex = draw(uint256(keccak256(abi.encodePacked(randomNumber, _disputeID, i))), k, nodes);
167175
bytes32 id = core.getSortitionSumTreeID(key, treeIndex);
168-
(
169-
address drawnAddress,
170-
/* subcourtID */
171-
) = stakePathIDToAccountAndSubcourtID(id);
176+
(address drawnAddress, /* subcourtID */) = stakePathIDToAccountAndSubcourtID(id);
172177

173178
// TODO: Save the vote.
174179
// dispute.votes[dispute.votes.length - 1][i].account = drawnAddress;

contracts/src/arbitration/mock/MockKlerosCore.sol

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22

33
pragma solidity ^0.8;
44

5-
import {SortitionSumTreeFactory} from "../../data-structures/SortitionSumTreeFactory.sol";
6-
// import "../DisputeKitPlurality.sol";
5+
// import {SortitionSumTreeFactory} from "../../data-structures/SortitionSumTreeFactory.sol";
76
import "../IArbitrable.sol";
87
import "../AbstractDisputeKit.sol";
98

109
contract MockKlerosCore {
11-
using SortitionSumTreeFactory for SortitionSumTreeFactory.SortitionSumTrees; // Use library functions for sortition sum trees.
12-
SortitionSumTreeFactory.SortitionSumTrees internal sortitionSumTrees; // The sortition sum trees.
10+
SortitionSumTrees internal sortitionSumTrees; // The sortition sum trees.
1311

1412
struct Dispute {
1513
// Note that appeal `0` is equivalent to the first round of the dispute.
@@ -45,6 +43,8 @@ contract MockKlerosCore {
4543
uint[4] timesPerPeriod; // The time allotted to each dispute period in the form `timesPerPeriod[period]`.
4644
}
4745

46+
event DisputeCreation(uint indexed _disputeID, IArbitrable indexed _arbitrable);
47+
4848
uint public constant MIN_JURORS = 3; // The global default minimum number of jurors in a dispute.
4949

5050
Dispute[] public disputes;
@@ -53,7 +53,10 @@ contract MockKlerosCore {
5353
AbstractDisputeKit disputeKit;
5454

5555
constructor() {
56-
sortitionSumTrees.createTree(bytes32(0), 3);
56+
createTree(sortitionSumTrees, bytes32(0), 3);
57+
Court storage court = courts.push();
58+
court.minStake = 100;
59+
court.feeForJuror = 100;
5760
}
5861

5962
// TODO: only owner
@@ -76,7 +79,7 @@ contract MockKlerosCore {
7679
_choices,
7780
_extraData);
7881

79-
//emit DisputeCreation(disputeID, IArbitrable(msg.sender));
82+
emit DisputeCreation(disputeID, IArbitrable(msg.sender));
8083
}
8184

8285
function getSortitionSumTree(bytes32 _key)
@@ -88,7 +91,7 @@ contract MockKlerosCore {
8891
uint256[] memory nodes
8992
)
9093
{
91-
SortitionSumTreeFactory.SortitionSumTree storage tree = sortitionSumTrees.sortitionSumTrees[_key];
94+
SortitionSumTree storage tree = sortitionSumTrees.sortitionSumTrees[_key];
9295
k = tree.K;
9396
stack = tree.stack;
9497
nodes = tree.nodes;
@@ -120,4 +123,35 @@ contract MockKlerosCore {
120123
minJurors = MIN_JURORS;
121124
}
122125
}
126+
127+
128+
// SORTITION TREE FACTORY
129+
130+
struct SortitionSumTree {
131+
uint256 K; // The maximum number of childs per node.
132+
// We use this to keep track of vacant positions in the tree after removing a leaf. This is for keeping the tree as balanced as possible without spending gas on moving nodes around.
133+
uint256[] stack;
134+
uint256[] nodes;
135+
// Two-way mapping of IDs to node indexes. Note that node index 0 is reserved for the root node, and means the ID does not have a node.
136+
mapping(bytes32 => uint256) IDsToNodeIndexes;
137+
mapping(uint256 => bytes32) nodeIndexesToIDs;
138+
}
139+
140+
struct SortitionSumTrees {
141+
mapping(bytes32 => SortitionSumTree) sortitionSumTrees;
142+
}
143+
144+
function createTree(
145+
SortitionSumTrees storage self,
146+
bytes32 _key,
147+
uint256 _K
148+
) private {
149+
SortitionSumTree storage tree = self.sortitionSumTrees[_key];
150+
require(tree.K == 0, "Tree already exists.");
151+
require(_K > 1, "K must be greater than one.");
152+
tree.K = _K;
153+
// tree.stack.length = 0;
154+
// tree.nodes.length = 0;
155+
tree.nodes.push(0);
156+
}
123157
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { expect } from "chai";
2+
import { ethers } from "hardhat";
3+
import { BigNumber } from "ethers";
4+
5+
const ONE_ETH = BigNumber.from(10).pow(18);
6+
const WINNER_STAKE_MULTIPLIER = 3000;
7+
const LOSER_STAKE_MULTIPLIER = 7000;
8+
const MULTIPLIER_DENOMINATOR = 10000;
9+
10+
function sleep(ms) {
11+
return new Promise((resolve) => setTimeout(resolve, ms));
12+
}
13+
14+
describe("DisputeKitPlurality", function () {
15+
// eslint-disable-next-line no-unused-vars
16+
let deployer, claimant, supporter, challenger, innocentBystander;
17+
let core, disputeKit, arbitrable;
18+
19+
before("Deploying", async () => {
20+
[deployer, claimant, supporter, challenger, innocentBystander] = await ethers.getSigners();
21+
[core, disputeKit, arbitrable] = await deployContracts(deployer);
22+
23+
// To wait for eth gas reporter to fetch data. Remove this line when the issue is fixed. https://github.com/cgewecke/hardhat-gas-reporter/issues/72
24+
// await sleep(9000);
25+
});
26+
27+
it("Should create a dispute", async function () {
28+
await expect(disputeKit.connect(deployer).createDispute(0, 0, 0, 0, 0, 0, "0x00"))
29+
.to.be.revertedWith("Not allowed: sender is not core");
30+
31+
await expect(core.connect(deployer).createDispute(2, "0x00", { value: 1000 }))
32+
.to.emit(core, "DisputeCreation")
33+
.withArgs(0, deployer.address);
34+
35+
console.log(await disputeKit.disputes(0));
36+
console.log(`votes=${await disputeKit.getVotes(0)}`);
37+
console.log(`votes=${await disputeKit.getVotesLength(0)}`);
38+
console.log(`voteCounter=${await disputeKit.getVoteCounter(0)}`);
39+
});
40+
});
41+
42+
43+
async function deployContracts(deployer) {
44+
const MockKlerosCoreFactory = await ethers.getContractFactory("MockKlerosCore", deployer);
45+
const core = await MockKlerosCoreFactory.deploy();
46+
await core.deployed();
47+
48+
const ConstantNGFactory = await ethers.getContractFactory("ConstantNG", deployer);
49+
const rng = await ConstantNGFactory.deploy(42);
50+
await rng.deployed();
51+
52+
const disputeKitFactory = await ethers.getContractFactory("DisputeKitPlurality", deployer);
53+
const disputeKit = await disputeKitFactory.deploy(core.address, rng.address);
54+
await disputeKit.deployed();
55+
56+
await core.registerDisputeKit(disputeKit.address);
57+
58+
const ArbitrableFactory = await ethers.getContractFactory("ArbitrableExample", deployer);
59+
const arbitrable = await ArbitrableFactory.deploy(core.address);
60+
await arbitrable.deployed();
61+
62+
return [core, disputeKit, arbitrable];
63+
}

0 commit comments

Comments
 (0)