Skip to content

Commit 7cb1275

Browse files
authored
Merge pull request #2154 from kleros/fix/contracts-review-round1
Contracts review feedback - round 1
2 parents 06db2d0 + 06cccaa commit 7cb1275

File tree

10 files changed

+45
-36
lines changed

10 files changed

+45
-36
lines changed

contracts/src/arbitration/KlerosCore.sol

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,8 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
424424
sortitionModule = _sortitionModule;
425425
}
426426

427-
/// @notice Add a new supported dispute kit module to the court.
427+
/// @notice Add a new supported dispute kit, without enabling it.
428+
/// Use `enableDisputeKits()` to enable the dispute kit for a specific court.
428429
/// @param _disputeKitAddress The address of the dispute kit contract.
429430
function addNewDisputeKit(IDisputeKit _disputeKitAddress) external onlyByOwner {
430431
uint256 disputeKitID = disputeKits.length;
@@ -461,7 +462,7 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
461462
Court storage court = courts.push();
462463

463464
for (uint256 i = 0; i < _supportedDisputeKits.length; i++) {
464-
if (_supportedDisputeKits[i] == 0 || _supportedDisputeKits[i] >= disputeKits.length) {
465+
if (_supportedDisputeKits[i] == NULL_DISPUTE_KIT || _supportedDisputeKits[i] >= disputeKits.length) {
465466
revert WrongDisputeKitIndex();
466467
}
467468
_enableDisputeKit(uint96(courtID), _supportedDisputeKits[i], true);
@@ -483,7 +484,7 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
483484
// Update the parent.
484485
courts[_parent].children.push(courtID);
485486
emit CourtCreated(
486-
uint96(courtID),
487+
courtID,
487488
_parent,
488489
_hiddenVotes,
489490
_minStake,
@@ -518,7 +519,7 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
518519
}
519520
for (uint256 i = 0; i < court.children.length; i++) {
520521
if (courts[court.children[i]].minStake < _minStake) {
521-
revert MinStakeLowerThanParentCourt();
522+
revert MinStakeHigherThanChildCourt(court.children[i]);
522523
}
523524
}
524525
court.minStake = _minStake;
@@ -544,10 +545,10 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
544545
/// @param _enable Whether add or remove the dispute kits from the court.
545546
function enableDisputeKits(uint96 _courtID, uint256[] memory _disputeKitIDs, bool _enable) external onlyByOwner {
546547
for (uint256 i = 0; i < _disputeKitIDs.length; i++) {
548+
if (_disputeKitIDs[i] == NULL_DISPUTE_KIT || _disputeKitIDs[i] >= disputeKits.length) {
549+
revert WrongDisputeKitIndex();
550+
}
547551
if (_enable) {
548-
if (_disputeKitIDs[i] == 0 || _disputeKitIDs[i] >= disputeKits.length) {
549-
revert WrongDisputeKitIndex();
550-
}
551552
_enableDisputeKit(_courtID, _disputeKitIDs[i], true);
552553
} else {
553554
// Classic dispute kit must be supported by all courts.
@@ -940,7 +941,7 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
940941
}
941942

942943
if (pnkBalance == 0 || !disputeKit.isVoteActive(_params.disputeID, _params.round, _params.repartition)) {
943-
// The juror is inactive or their balance is can't cover penalties anymore, unstake them from all courts.
944+
// The juror is inactive or their balance can't cover penalties anymore, unstake them from all courts.
944945
sortitionModule.forcedUnstakeAllCourts(account);
945946
} else if (newCourtStake < courts[penalizedInCourtID].minStake) {
946947
// The juror's balance fell below the court minStake, unstake them from the court.
@@ -1365,7 +1366,7 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
13651366
function _extraDataToCourtIDMinJurorsDisputeKit(
13661367
bytes memory _extraData
13671368
) internal view returns (uint96 courtID, uint256 minJurors, uint256 disputeKitID) {
1368-
// Note that if the extradata doesn't contain 32 bytes for the dispute kit ID it'll return the default 0 index.
1369+
// Note that if the _extraData doesn't contain 32 bytes, default values are used.
13691370
if (_extraData.length >= 64) {
13701371
assembly {
13711372
// solium-disable-line security/no-inline-assembly
@@ -1380,7 +1381,7 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
13801381
minJurors = DEFAULT_NB_OF_JURORS;
13811382
}
13821383
if (disputeKitID == NULL_DISPUTE_KIT || disputeKitID >= disputeKits.length) {
1383-
disputeKitID = DISPUTE_KIT_CLASSIC; // 0 index is not used.
1384+
disputeKitID = DISPUTE_KIT_CLASSIC;
13841385
}
13851386
} else {
13861387
courtID = GENERAL_COURT;
@@ -1398,8 +1399,9 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
13981399
error DisputeKitOnly();
13991400
error SortitionModuleOnly();
14001401
error UnsuccessfulCall();
1401-
error InvalidDisputKitParent();
1402+
error InvalidDisputeKitParent();
14021403
error MinStakeLowerThanParentCourt();
1404+
error MinStakeHigherThanChildCourt(uint256 _childCourtID);
14031405
error UnsupportedDisputeKit();
14041406
error InvalidForkingCourtAsParent();
14051407
error WrongDisputeKitIndex();

contracts/src/arbitration/SortitionModule.sol

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
5353
mapping(TreeKey key => SortitionTrees.Tree) sortitionSumTrees; // The mapping of sortition trees by keys.
5454
mapping(address account => Juror) public jurors; // The jurors.
5555
mapping(uint256 => DelayedStake) public delayedStakes; // Stores the stakes that were changed during Drawing phase, to update them when the phase is switched to Staking.
56-
uint256 public maxStakePerJuror; // The maximum amount of PNK a juror can stake in a court.
57-
uint256 public maxTotalStaked; // The maximum amount of PNK that can be staked in all courts.
58-
uint256 public totalStaked; // The amount that is currently staked in all courts.
56+
uint256 public maxStakePerJuror; // The maximum amount of PNK that a juror can stake across the courts.
57+
uint256 public maxTotalStaked; // The maximum amount of PNK that all the jurors can stake across the courts.
58+
uint256 public totalStaked; // The amount of PNK that is currently staked across the courts.
5959

6060
// ************************************* //
6161
// * Events * //
@@ -105,8 +105,8 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
105105
/// @param _minStakingTime Minimal time to stake
106106
/// @param _maxDrawingTime Time after which the drawing phase can be switched
107107
/// @param _rng The random number generator.
108-
/// @param _maxStakePerJuror The maximum amount of PNK a juror can stake in a court.
109-
/// @param _maxTotalStaked The maximum amount of PNK that can be staked in all courts.
108+
/// @param _maxStakePerJuror The maximum amount of PNK a juror can stake across the courts.
109+
/// @param _maxTotalStaked The maximum amount of PNK that all the jurors can stake across the courts.
110110
function initialize(
111111
address _owner,
112112
KlerosCore _core,
@@ -343,14 +343,14 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
343343

344344
if (availablePenalty == 0) return (juror.stakedPnk, newCourtStake, 0); // No penalty to apply.
345345

346-
uint256 currentStake = _stakeOf(_account, _courtID);
346+
uint256 currentStake = newCourtStake;
347347
uint256 newStake = 0;
348348
if (currentStake >= availablePenalty) {
349349
newStake = currentStake - availablePenalty;
350350
}
351351
_setStake(_account, _courtID, 0, availablePenalty, newStake);
352352
pnkBalance = juror.stakedPnk; // updated by _setStake()
353-
newCourtStake = _stakeOf(_account, _courtID); // updated by _setStake()
353+
newCourtStake = newStake;
354354
}
355355

356356
/// @inheritdoc ISortitionModule

contracts/src/arbitration/arbitrables/DisputeResolver.sol

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,22 @@ contract DisputeResolver is IArbitrableV2 {
3030
DisputeStruct[] public disputes; // Local disputes.
3131
mapping(uint256 => uint256) public arbitratorDisputeIDToLocalID; // Maps arbitrator-side dispute IDs to local dispute IDs.
3232

33+
// ************************************* //
34+
// * Function Modifiers * //
35+
// ************************************* //
36+
37+
modifier onlyByOwner() {
38+
if (owner != msg.sender) revert OwnerOnly();
39+
_;
40+
}
41+
3342
// ************************************* //
3443
// * Constructor * //
3544
// ************************************* //
3645

3746
/// @notice Constructor
3847
/// @param _arbitrator Target global arbitrator for any disputes.
48+
/// @param _templateRegistry The dispute template registry.
3949
constructor(IArbitratorV2 _arbitrator, IDisputeTemplateRegistry _templateRegistry) {
4050
owner = msg.sender;
4151
arbitrator = _arbitrator;
@@ -48,18 +58,15 @@ contract DisputeResolver is IArbitrableV2 {
4858

4959
/// @notice Changes the owner.
5060
/// @param _owner The address of the new owner.
51-
function changeOwner(address _owner) external {
52-
if (owner != msg.sender) revert OwnerOnly();
61+
function changeOwner(address _owner) external onlyByOwner {
5362
owner = _owner;
5463
}
5564

56-
function changeArbitrator(IArbitratorV2 _arbitrator) external {
57-
if (owner != msg.sender) revert OwnerOnly();
65+
function changeArbitrator(IArbitratorV2 _arbitrator) external onlyByOwner {
5866
arbitrator = _arbitrator;
5967
}
6068

61-
function changeTemplateRegistry(IDisputeTemplateRegistry _templateRegistry) external {
62-
if (owner != msg.sender) revert OwnerOnly();
69+
function changeTemplateRegistry(IDisputeTemplateRegistry _templateRegistry) external onlyByOwner {
6370
templateRegistry = _templateRegistry;
6471
}
6572

contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
370370
if (!coreDisputeIDToActive[_coreDisputeID]) revert NotActiveForCoreDisputeID();
371371

372372
(uint256 appealPeriodStart, uint256 appealPeriodEnd) = core.appealPeriod(_coreDisputeID);
373-
if (block.timestamp < appealPeriodStart || block.timestamp >= appealPeriodEnd) revert AppealPeriodIsOver();
373+
if (block.timestamp < appealPeriodStart || block.timestamp >= appealPeriodEnd) revert NotAppealPeriod();
374374

375375
uint256 multiplier;
376376
(uint256 ruling, , ) = this.currentRuling(_coreDisputeID);
@@ -381,7 +381,7 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
381381
block.timestamp - appealPeriodStart >=
382382
((appealPeriodEnd - appealPeriodStart) * LOSER_APPEAL_PERIOD_MULTIPLIER) / ONE_BASIS_POINT
383383
) {
384-
revert AppealPeriodIsOverForLoser();
384+
revert NotAppealPeriodForLoser();
385385
}
386386
multiplier = LOSER_STAKE_MULTIPLIER;
387387
}
@@ -759,8 +759,8 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
759759
error ChoiceOutOfBounds();
760760
error HashDoesNotMatchHiddenVoteCommitment();
761761
error VoteAlreadyCast();
762-
error AppealPeriodIsOver();
763-
error AppealPeriodIsOverForLoser();
762+
error NotAppealPeriod();
763+
error NotAppealPeriodForLoser();
764764
error AppealFeeIsAlreadyPaid();
765765
error DisputeNotResolved();
766766
error CoreIsPaused();

contracts/src/arbitration/interfaces/IArbitratorV2.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ interface IArbitratorV2 {
5050
) external payable returns (uint256 disputeID);
5151

5252
/// @notice Create a dispute and pay for the fees in a supported ERC20 token.
53-
/// @dev Must be called by the arbitrable contract and pay at least `arbitrationCost(_extraData)` in the supported ERC20 token.
53+
/// @dev Must be called by the arbitrable contract and pay at least `arbitrationCost(_extraData, _feeToken)` in the supported ERC20 token.
5454
/// @param _numberOfChoices The number of choices the arbitrator can choose from in this dispute.
5555
/// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes).
5656
/// @param _feeToken The ERC20 token used to pay fees.

contracts/src/arbitration/interfaces/IEvidence.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pragma solidity >=0.8.0 <0.9.0;
66
interface IEvidence {
77
/// @notice To be raised when evidence is submitted. Should point to the resource (evidences are not to be stored on chain due to gas considerations).
88
/// @param _externalDisputeID Unique identifier for this dispute outside Kleros. It's the submitter responsibility to submit the right external dispute ID.
9-
/// @param _party The address of the party submiting the evidence. Note that 0x0 refers to evidence not submitted by any party.
9+
/// @param _party The address of the party submitting the evidence.
1010
/// @param _evidence Stringified evidence object, example: '{"name" : "Justification", "description" : "Description", "fileURI" : "/ipfs/QmWQV5ZFFhEJiW8Lm7ay2zLxC2XS4wx1b2W7FfdrLMyQQc"}'.
1111
event Evidence(uint256 indexed _externalDisputeID, address indexed _party, string _evidence);
1212
}

contracts/src/arbitration/interfaces/ISortitionModule.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ interface ISortitionModule {
7878
uint256 _newStake
7979
) external;
8080

81-
/// @notice Update the state of the stakes with a PNK reward deposit, called by KC during rewards execution.
81+
/// @notice Update the state of the stakes with a PNK penalty, called by KC during rewards execution.
8282
///
8383
/// @dev `O(n + p * log_k(j))` where
8484
/// `n` is the number of courts the juror has staked in,

contracts/src/arbitration/university/KlerosCoreUniversity.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1173,7 +1173,7 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable {
11731173
error DisputeKitOnly();
11741174
error SortitionModuleOnly();
11751175
error UnsuccessfulCall();
1176-
error InvalidDisputKitParent();
1176+
error InvalidDisputeKitParent();
11771177
error MinStakeLowerThanParentCourt();
11781178
error UnsupportedDisputeKit();
11791179
error InvalidForkingCourtAsParent();

contracts/test/foundry/KlerosCore_Appeals.t.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,22 +127,22 @@ contract KlerosCore_AppealsTest is KlerosCore_TestBase {
127127
disputeKit.castVote(disputeID, voteIDs, 2, 0, "XYZ");
128128

129129
vm.prank(crowdfunder1);
130-
vm.expectRevert(DisputeKitClassicBase.AppealPeriodIsOver.selector);
130+
vm.expectRevert(DisputeKitClassicBase.NotAppealPeriod.selector);
131131
disputeKit.fundAppeal{value: 0.1 ether}(disputeID, 1);
132132
core.passPeriod(disputeID);
133133

134134
(uint256 start, uint256 end) = core.appealPeriod(0);
135135

136136
vm.prank(crowdfunder1);
137137
vm.warp(block.timestamp + ((end - start) / 2 + 1));
138-
vm.expectRevert(DisputeKitClassicBase.AppealPeriodIsOverForLoser.selector);
138+
vm.expectRevert(DisputeKitClassicBase.NotAppealPeriodForLoser.selector);
139139
disputeKit.fundAppeal{value: 0.1 ether}(disputeID, 1); // Losing choice
140140

141141
disputeKit.fundAppeal(disputeID, 2); // Winning choice funding should not revert yet
142142

143143
vm.prank(crowdfunder1);
144144
vm.warp(block.timestamp + (end - start) / 2); // Warp one more to cover the whole period
145-
vm.expectRevert(DisputeKitClassicBase.AppealPeriodIsOver.selector);
145+
vm.expectRevert(DisputeKitClassicBase.NotAppealPeriod.selector);
146146
disputeKit.fundAppeal{value: 0.1 ether}(disputeID, 2);
147147
}
148148

contracts/test/foundry/KlerosCore_Governance.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ contract KlerosCore_GovernanceTest is KlerosCore_TestBase {
310310
50, // jurors for jump
311311
[uint256(10), uint256(20), uint256(30), uint256(40)] // Times per period
312312
);
313-
vm.expectRevert(KlerosCore.MinStakeLowerThanParentCourt.selector);
313+
vm.expectRevert(abi.encodeWithSelector(KlerosCore.MinStakeHigherThanChildCourt.selector, newCourtID));
314314
vm.prank(owner);
315315
// Min stake of a parent became higher than of a child
316316
core.changeCourtParameters(

0 commit comments

Comments
 (0)