Skip to content

Commit 6a2490e

Browse files
committed
feat(DisputeKitPlurality): dispute creation
1 parent f339e2b commit 6a2490e

File tree

4 files changed

+193
-23
lines changed

4 files changed

+193
-23
lines changed

CHANGELOG.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
## 0.1.0 (2021-12-17)
1+
## 0.1.0 (2021-12-18)
22

3+
- feat: add arbitrum L1 bridge and dependencies ([b412772](https://github.com/kleros/kleros-v2/commit/b412772))
4+
- feat: add arbitrum L2 bridge ([457b060](https://github.com/kleros/kleros-v2/commit/457b060))
5+
- feat: dispute kit in progress ([95b8ada](https://github.com/kleros/kleros-v2/commit/95b8ada))
6+
- feat: modern toolchain setup and simple RNG smart contracts ([17f6a76](https://github.com/kleros/kleros-v2/commit/17f6a76))
7+
- feat(Arbitration): standard update ([ed930de](https://github.com/kleros/kleros-v2/commit/ed930de))
8+
- feat(DisputeKitPlurality): split the responsibility of drawing jurors between Core and Dispute Kit ([f339e2b](https://github.com/kleros/kleros-v2/commit/f339e2b))
39
- refactor: add arbitrator data index getter ([47a1623](https://github.com/kleros/kleros-v2/commit/47a1623))
410
- refactor: add evidence contracts ([09a34f3](https://github.com/kleros/kleros-v2/commit/09a34f3))
511
- refactor: add interfaces + capped math ([e25b21f](https://github.com/kleros/kleros-v2/commit/e25b21f))
@@ -8,11 +14,6 @@
814
- refactor: remove foreign evidence interface ([ff8c50c](https://github.com/kleros/kleros-v2/commit/ff8c50c))
915
- refactor(bridge): use ArbRetryableTx#getSubmissionPrice ([61bc2f3](https://github.com/kleros/kleros-v2/commit/61bc2f3))
1016
- refactor(sdk): rename ([3241d10](https://github.com/kleros/kleros-v2/commit/3241d10))
11-
- feat: add arbitrum L1 bridge and dependencies ([b412772](https://github.com/kleros/kleros-v2/commit/b412772))
12-
- feat: add arbitrum L2 bridge ([457b060](https://github.com/kleros/kleros-v2/commit/457b060))
13-
- feat: dispute kit in progress ([95b8ada](https://github.com/kleros/kleros-v2/commit/95b8ada))
14-
- feat: modern toolchain setup and simple RNG smart contracts ([17f6a76](https://github.com/kleros/kleros-v2/commit/17f6a76))
15-
- feat(Arbitration): standard update ([ed930de](https://github.com/kleros/kleros-v2/commit/ed930de))
1617
- chore: .gitignore ([0ed4d74](https://github.com/kleros/kleros-v2/commit/0ed4d74))
1718
- chore: .gitignore and removal of unnecessary yarn cache as we are using "zero installs" ([a6cfdd0](https://github.com/kleros/kleros-v2/commit/a6cfdd0))
1819
- chore: added GitHub code scanning ([4a70475](https://github.com/kleros/kleros-v2/commit/4a70475))
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8;
4+
5+
import "./IArbitrator.sol";
6+
7+
abstract contract AbstractDisputeKit {
8+
9+
/**
10+
* Note: disputeID is maintained by Kleros Core, not the dispute kit
11+
* Note: the dispute kit does not receive any payment, Kleros Core does
12+
* Note: Permissioned
13+
*/
14+
function createDispute(
15+
uint256 _disputeID,
16+
uint256 _arbitrationFee,
17+
uint256 _subcourtFeeForJuror,
18+
uint256 _subcourtMinStake,
19+
uint256 _subcourtAlpha,
20+
uint256 _choices,
21+
bytes calldata _extraData
22+
) external virtual;
23+
24+
/**
25+
* @dev Draws jurors for a dispute. Can be called in parts.
26+
* @param _disputeID The ID of the dispute.
27+
* @param _iterations The number of iterations to run.
28+
*/
29+
function drawJurors(uint256 _disputeID, uint256 _iterations) external virtual;
30+
31+
}

contracts/src/arbitration/DisputeKitPlurality.sol

Lines changed: 94 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import "./IArbitrator.sol";
66
import "../rng/RNG.sol";
77
import "./mock/MockKlerosCore.sol";
88

9-
contract DisputeKitPlurality {
9+
contract DisputeKitPlurality is AbstractDisputeKit {
1010
// Core --> IN
1111
// createDispute
1212

@@ -28,27 +28,86 @@ contract DisputeKitPlurality {
2828
// appeal crowdfunding
2929
// redistribution when ruling is final
3030

31+
// ************************ //
32+
// * STRUCTS * //
33+
// ************************ //
34+
struct Vote {
35+
address account; // The address of the juror.
36+
bytes32 commit; // The commit of the juror. For courts with hidden votes.
37+
uint choice; // The choice of the juror.
38+
bool voted; // True if the vote has been cast or revealed, false otherwise.
39+
}
40+
struct VoteCounter {
41+
// The choice with the most votes. Note that in the case of a tie, it is the choice that reached the tied number of votes first.
42+
uint winningChoice;
43+
mapping(uint => uint) counts; // The sum of votes for each choice in the form `counts[choice]`.
44+
bool tied; // True if there is a tie, false otherwise.
45+
}
46+
struct Dispute {
47+
//NOTE: arbitrated needed?? But it needs the chainId too, not just an address.
48+
//IArbitrable arbitrated; // The address of the arbitrable contract.
49+
bytes arbitratorExtraData; // Extra data for the arbitrator.
50+
uint256 choices; // The number of choices the arbitrator can choose from.
51+
uint256 appealPeriodStart; // Time when the appeal funding becomes possible.
52+
Vote[][] votes; // The votes in the form `votes[appeal][voteID]`. On each round, a new list is pushed and packed with as many empty votes as there are draws. We use `dispute.votes.length` to get the number of appeals plus 1 for the first round.
53+
VoteCounter[] voteCounters; // The vote counters in the form `voteCounters[appeal]`.
54+
uint[] tokensAtStakePerJurorForRound; // The amount of tokens at stake for each juror in the form `tokensAtStakePerJuror[appeal]`.
55+
uint[] arbitrationFeeForRound; // Fee paid by the arbitrable for the arbitration for each round. Must be equal or higher than arbitration cost.
56+
uint drawsInCurrentRound; // A counter of draws made in the current round.
57+
uint commitsInCurrentRound; // A counter of commits made in the current round.
58+
uint[] votesForRound; // A counter of votes made in each round in the form `votesInEachRound[appeal]`.
59+
uint[] repartitionsForRound; // A counter of vote reward repartitions made in each round in the form `repartitionsInEachRound[appeal]`.
60+
uint[] penaltiesForRound; // The amount of tokens collected from penalties in each round in the form `penaltiesInEachRound[appeal]`.
61+
bool ruled; // True if the ruling has been executed, false otherwise.
62+
uint256 ruling; // Ruling given by the arbitrator.
63+
}
64+
65+
struct Round {
66+
mapping(uint256 => uint256) paidFees; // Tracks the fees paid for each choice in this round.
67+
mapping(uint256 => bool) hasPaid; // True if this choice was fully funded, false otherwise.
68+
mapping(address => mapping(uint256 => uint256)) contributions; // Maps contributors to their contributions for each choice.
69+
uint256 feeRewards; // Sum of reimbursable appeal fees available to the parties that made contributions to the ruling that ultimately wins a dispute.
70+
uint256[] fundedChoices; // Stores the choices that are fully funded.
71+
}
72+
73+
// ************************ //
74+
// * STORAGE * //
75+
// ************************ //
76+
77+
uint public constant ALPHA_DIVISOR = 1e4; // The number to divide `Court.alpha` by.
78+
3179
// TODO: extract the necessary interfaces
3280
MockKlerosCore public immutable core;
3381

3482
RNG public immutable rng;
3583

84+
Dispute[] public disputes; // Stores the dispute info. disputes[disputeID].
85+
mapping(uint256 => Round[]) public disputeIDtoRounds; // Maps dispute IDs to Round array that contains the info about crowdfunding.
86+
87+
3688
constructor(MockKlerosCore _core, RNG _rng) {
3789
core = _core;
3890
rng = _rng;
3991
}
4092

93+
// ************************ //
94+
// * MODIFIERS * //
95+
// ************************ //
96+
4197
/**
42-
* Note: disputeID is maintained by Kleros Core, not the dispute kit
43-
* Note: the dispute kit does not receive any payment, Kleros Core does
98+
* Note: disputeID is maintained by KlerosCore, not the dispute kit
99+
* Note: the dispute kit does not receive nor validate any payment, KlerosCore does
44100
* Note: Permissioned
45101
*/
46102
function createDispute(
47103
uint256 _disputeID,
48-
uint256 _minJuror,
104+
uint256 _arbitrationFee,
105+
uint256 _subcourtFeeForJuror,
106+
uint256 _subcourtMinStake,
107+
uint256 _subcourtAlpha,
49108
uint256 _choices,
50109
bytes calldata _extraData
51-
) external {
110+
) external override {
52111
require(msg.sender == address(core), "Not allowed: sender is not core");
53112

54113
// -- dispute specific --
@@ -61,24 +120,41 @@ contract DisputeKitPlurality {
61120
// uint feeForJuror: paid per juror
62121
// uint jurorsForCourtJump: evaluated by the appeal logic
63122

64-
// PROBLEM: have an interface that works for and "1 human 1 vote"
123+
// NOTE: the interface should work also for "1 human 1 vote"
124+
125+
126+
Dispute storage dispute = disputes.push();
127+
dispute.arbitratorExtraData = _extraData;
128+
dispute.choices = _choices;
129+
dispute.appealPeriodStart = 0;
65130

66-
// votes = msg.value / subcourt.feeForJuror
67-
// tokenAtStakePerJuror = (subcourt.minStake * subcourt.alpha) / ALPHA_DIVISOR
68-
// ALPHA_DIVISOR = 10000
131+
uint numberOfVotes = _arbitrationFee / _subcourtFeeForJuror;
132+
Vote[] storage votes = dispute.votes.push(); // TODO: the array dimensions may be reversed, check!
133+
while (votes.length < numberOfVotes)
134+
votes.push();
135+
136+
dispute.voteCounters.push().tied = true;
137+
dispute.tokensAtStakePerJurorForRound.push((_subcourtMinStake * _subcourtAlpha) / ALPHA_DIVISOR);
138+
dispute.arbitrationFeeForRound.push(_arbitrationFee);
139+
dispute.votesForRound.push(0);
140+
dispute.repartitionsForRound.push(0);
141+
dispute.penaltiesForRound.push(0);
142+
dispute.ruling = 0;
143+
144+
disputeIDtoRounds[_disputeID].push();
69145
}
70146

71147
/**
72148
* @dev Draws jurors for a dispute. Can be called in parts.
73149
* @param _disputeID The ID of the dispute.
74150
* @param _iterations The number of iterations to run.
75151
*/
76-
function drawJurors(uint256 _disputeID, uint256 _iterations) public {
152+
function drawJurors(uint256 _disputeID, uint256 _iterations) external override {
77153
uint96 subcourtID = core.getDispute(_disputeID).subcourtID;
78154
bytes32 key = bytes32(bytes12(subcourtID)); // due to new conversion restrictions in v0.8
79155
(
80-
uint256 k, /* stack */
81-
,
156+
uint256 k,
157+
/* stack */ ,
82158
uint256[] memory nodes
83159
) = core.getSortitionSumTree(key);
84160

@@ -90,8 +166,8 @@ contract DisputeKitPlurality {
90166
uint256 treeIndex = draw(uint256(keccak256(abi.encodePacked(randomNumber, _disputeID, i))), k, nodes);
91167
bytes32 id = core.getSortitionSumTreeID(key, treeIndex);
92168
(
93-
address drawnAddress, /* subcourtID */
94-
169+
address drawnAddress,
170+
/* subcourtID */
95171
) = stakePathIDToAccountAndSubcourtID(id);
96172

97173
// TODO: Save the vote.
@@ -104,6 +180,10 @@ contract DisputeKitPlurality {
104180
}
105181
}
106182

183+
// ************************ //
184+
// * VIEWS * //
185+
// ************************ //
186+
107187
function draw(
108188
uint256 _drawnNumber,
109189
uint256 _k,

contracts/src/arbitration/mock/MockKlerosCore.sol

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pragma solidity ^0.8;
55
import {SortitionSumTreeFactory} from "../../data-structures/SortitionSumTreeFactory.sol";
66
// import "../DisputeKitPlurality.sol";
77
import "../IArbitrable.sol";
8+
import "../AbstractDisputeKit.sol";
89

910
contract MockKlerosCore {
1011
using SortitionSumTreeFactory for SortitionSumTreeFactory.SortitionSumTrees; // Use library functions for sortition sum trees.
@@ -32,25 +33,63 @@ contract MockKlerosCore {
3233
bool ruled; // True if the ruling has been executed, false otherwise.
3334
}
3435

36+
struct Court {
37+
uint96 parent; // The parent court.
38+
uint[] children; // List of child courts.
39+
bool hiddenVotes; // Whether to use commit and reveal or not.
40+
uint minStake; // Minimum tokens needed to stake in the court.
41+
uint alpha; // Basis point of tokens that are lost when incoherent.
42+
uint feeForJuror; // Arbitration fee paid per juror.
43+
// The appeal after the one that reaches this number of jurors will go to the parent court if any, otherwise, no more appeals are possible.
44+
uint jurorsForCourtJump;
45+
uint[4] timesPerPeriod; // The time allotted to each dispute period in the form `timesPerPeriod[period]`.
46+
}
47+
48+
uint public constant MIN_JURORS = 3; // The global default minimum number of jurors in a dispute.
49+
3550
Dispute[] public disputes;
51+
Court[] public courts;
52+
53+
AbstractDisputeKit disputeKit;
3654

3755
constructor() {
3856
sortitionSumTrees.createTree(bytes32(0), 3);
3957
}
4058

41-
// DisputeKitPlurality disputeKit;
59+
// TODO: only owner
60+
function registerDisputeKit(AbstractDisputeKit _disputeKit) external {
61+
disputeKit = _disputeKit;
62+
}
63+
64+
function createDispute(uint256 _choices, bytes calldata _extraData) external payable returns (uint256 disputeID) {
65+
(uint96 subcourtID, uint minJurors) = extraDataToSubcourtIDAndMinJurors(_extraData);
66+
disputeID = disputes.length;
67+
68+
Court storage court = courts[0];
69+
70+
disputeKit.createDispute(
71+
disputeID,
72+
msg.value,
73+
court.feeForJuror,
74+
court.minStake,
75+
court.alpha,
76+
_choices,
77+
_extraData);
78+
79+
//emit DisputeCreation(disputeID, IArbitrable(msg.sender));
80+
}
4281

4382
function getSortitionSumTree(bytes32 _key)
4483
public
4584
view
4685
returns (
47-
uint256 K,
86+
uint256 k,
4887
uint256[] memory stack,
4988
uint256[] memory nodes
5089
)
5190
{
5291
SortitionSumTreeFactory.SortitionSumTree storage tree = sortitionSumTrees.sortitionSumTrees[_key];
53-
K = tree.K;
92+
k = tree.K;
5493
stack = tree.stack;
5594
nodes = tree.nodes;
5695
}
@@ -62,4 +101,23 @@ contract MockKlerosCore {
62101
function getDispute(uint256 _id) public view returns (Dispute memory) {
63102
return disputes[_id];
64103
}
104+
105+
/** @dev Gets a subcourt ID and the minimum number of jurors required from a specified extra data bytes array.
106+
* @param _extraData The extra data bytes array. The first 32 bytes are the subcourt ID and the next 32 bytes are the minimum number of jurors.
107+
* @return subcourtID The subcourt ID.
108+
* @return minJurors The minimum number of jurors required.
109+
*/
110+
function extraDataToSubcourtIDAndMinJurors(bytes memory _extraData) internal view returns (uint96 subcourtID, uint minJurors) {
111+
if (_extraData.length >= 64) {
112+
assembly { // solium-disable-line security/no-inline-assembly
113+
subcourtID := mload(add(_extraData, 0x20))
114+
minJurors := mload(add(_extraData, 0x40))
115+
}
116+
if (subcourtID >= courts.length) subcourtID = 0;
117+
if (minJurors == 0) minJurors = MIN_JURORS;
118+
} else {
119+
subcourtID = 0;
120+
minJurors = MIN_JURORS;
121+
}
122+
}
65123
}

0 commit comments

Comments
 (0)