Skip to content

Commit 78833f3

Browse files
committed
chore: tweaked sortition module natspec, added the phase related functions to the interface
1 parent 96bb505 commit 78833f3

File tree

3 files changed

+181
-135
lines changed

3 files changed

+181
-135
lines changed

contracts/src/arbitration/SortitionModule.sol

Lines changed: 38 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
194194
// * State Modifiers * //
195195
// ************************************* //
196196

197-
/// @dev Passes the phase.
198-
function passPhase() external {
197+
/// @inheritdoc ISortitionModule
198+
function passPhase() external override {
199199
if (phase == Phase.staking) {
200200
if (block.timestamp - lastPhaseChange < minStakingTime) revert MinStakingTimeNotPassed();
201201
if (disputesWithoutJurors == 0) revert NoDisputesThatNeedJurors();
@@ -216,18 +216,15 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
216216
emit NewPhase(phase);
217217
}
218218

219-
/// @dev Create a sortition sum tree at the specified key.
220-
/// @param _courtID The ID of the court.
221-
/// @param _extraData Extra data that contains the number of children each node in the tree should have.
219+
/// @inheritdoc ISortitionModule
222220
function createTree(uint96 _courtID, bytes memory _extraData) external override onlyByCore {
223221
TreeKey key = CourtID.wrap(_courtID).toTreeKey();
224222
uint256 K = _extraDataToTreeK(_extraData);
225223
sortitionSumTrees.createTree(key, K);
226224
}
227225

228-
/// @dev Executes the next delayed stakes.
229-
/// @param _iterations The number of delayed stakes to execute.
230-
function executeDelayedStakes(uint256 _iterations) external {
226+
/// @inheritdoc ISortitionModule
227+
function executeDelayedStakes(uint256 _iterations) external override {
231228
if (phase != Phase.staking) revert NotStakingPhase();
232229
if (delayedStakeWriteIndex < delayedStakeReadIndex) revert NoDelayedStakeToExecute();
233230

@@ -244,29 +241,17 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
244241
delayedStakeReadIndex = newDelayedStakeReadIndex;
245242
}
246243

247-
/// @dev Triggers the state changes after dispute creation.
244+
/// @inheritdoc ISortitionModule
248245
function createDisputeHook(uint256 /*_disputeID*/, uint256 /*_roundID*/) external override onlyByCore {
249246
disputesWithoutJurors++;
250247
}
251248

252-
/// @dev Triggers the state changes after drawing.
249+
/// @inheritdoc ISortitionModule
253250
function postDrawHook(uint256 /*_disputeID*/, uint256 /*_roundID*/) external override onlyByCore {
254251
disputesWithoutJurors--;
255252
}
256253

257-
/// @dev Saves the random number to use it in sortition. Not used by this contract because the storing of the number is inlined in passPhase().
258-
/// @param _randomNumber Random number returned by RNG contract.
259-
function notifyRandomNumber(uint256 _randomNumber) public override {}
260-
261-
/// @dev Validate the specified juror's new stake for a court.
262-
/// Note: no state changes should be made when returning stakingResult != Successful, otherwise delayed stakes might break invariants.
263-
/// @param _account The address of the juror.
264-
/// @param _courtID The ID of the court.
265-
/// @param _newStake The new stake.
266-
/// @param _noDelay True if the stake change should not be delayed.
267-
/// @return pnkDeposit The amount of PNK to be deposited.
268-
/// @return pnkWithdrawal The amount of PNK to be withdrawn.
269-
/// @return stakingResult The result of the staking operation.
254+
/// @inheritdoc ISortitionModule
270255
function validateStake(
271256
address _account,
272257
uint96 _courtID,
@@ -283,7 +268,7 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
283268
bool _noDelay
284269
) internal returns (uint256 pnkDeposit, uint256 pnkWithdrawal, StakingResult stakingResult) {
285270
Juror storage juror = jurors[_account];
286-
uint256 currentStake = stakeOf(_account, _courtID);
271+
uint256 currentStake = _stakeOf(_account, _courtID);
287272
bool stakeIncrease = _newStake > currentStake;
288273
uint256 stakeChange = stakeIncrease ? _newStake - currentStake : currentStake - _newStake;
289274

@@ -332,17 +317,7 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
332317
return (pnkDeposit, pnkWithdrawal, StakingResult.Successful);
333318
}
334319

335-
/// @dev Update the state of the stakes, called by KC at the end of setStake flow.
336-
/// `O(n + p * log_k(j))` where
337-
/// `n` is the number of courts the juror has staked in,
338-
/// `p` is the depth of the court tree,
339-
/// `k` is the minimum number of children per node of one of these courts' sortition sum tree,
340-
/// and `j` is the maximum number of jurors that ever staked in one of these courts simultaneously.
341-
/// @param _account The address of the juror.
342-
/// @param _courtID The ID of the court.
343-
/// @param _pnkDeposit The amount of PNK to be deposited.
344-
/// @param _pnkWithdrawal The amount of PNK to be withdrawn.
345-
/// @param _newStake The new stake.
320+
/// @inheritdoc ISortitionModule
346321
function setStake(
347322
address _account,
348323
uint96 _courtID,
@@ -353,59 +328,40 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
353328
_setStake(_account, _courtID, _pnkDeposit, _pnkWithdrawal, _newStake);
354329
}
355330

356-
/// @dev Update the state of the stakes with a PNK reward deposit, called by KC during rewards execution.
357-
/// `O(n + p * log_k(j))` where
358-
/// `n` is the number of courts the juror has staked in,
359-
/// `p` is the depth of the court tree,
360-
/// `k` is the minimum number of children per node of one of these courts' sortition sum tree,
361-
/// and `j` is the maximum number of jurors that ever staked in one of these courts simultaneously.
362-
/// @param _account The address of the juror.
363-
/// @param _courtID The ID of the court.
364-
/// @param _penalty The amount of PNK to be deducted.
365-
/// @return pnkBalance The updated total PNK balance of the juror, including the penalty.
366-
/// @return newCourtStake The updated stake of the juror in the court.
367-
/// @return availablePenalty The amount of PNK that was actually deducted.
331+
/// @inheritdoc ISortitionModule
368332
function setStakePenalty(
369333
address _account,
370334
uint96 _courtID,
371335
uint256 _penalty
372336
) external override onlyByCore returns (uint256 pnkBalance, uint256 newCourtStake, uint256 availablePenalty) {
373337
Juror storage juror = jurors[_account];
374338
availablePenalty = _penalty;
375-
newCourtStake = stakeOf(_account, _courtID);
339+
newCourtStake = _stakeOf(_account, _courtID);
376340
if (juror.stakedPnk < _penalty) {
377341
availablePenalty = juror.stakedPnk;
378342
}
379343

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

382-
uint256 currentStake = stakeOf(_account, _courtID);
346+
uint256 currentStake = _stakeOf(_account, _courtID);
383347
uint256 newStake = 0;
384348
if (currentStake >= availablePenalty) {
385349
newStake = currentStake - availablePenalty;
386350
}
387351
_setStake(_account, _courtID, 0, availablePenalty, newStake);
388352
pnkBalance = juror.stakedPnk; // updated by _setStake()
389-
newCourtStake = stakeOf(_account, _courtID); // updated by _setStake()
353+
newCourtStake = _stakeOf(_account, _courtID); // updated by _setStake()
390354
}
391355

392-
/// @dev Update the state of the stakes with a PNK reward deposit, called by KC during rewards execution.
393-
/// `O(n + p * log_k(j))` where
394-
/// `n` is the number of courts the juror has staked in,
395-
/// `p` is the depth of the court tree,
396-
/// `k` is the minimum number of children per node of one of these courts' sortition sum tree,
397-
/// and `j` is the maximum number of jurors that ever staked in one of these courts simultaneously.
398-
/// @param _account The address of the juror.
399-
/// @param _courtID The ID of the court.
400-
/// @param _reward The amount of PNK to be deposited as a reward.
356+
/// @inheritdoc ISortitionModule
401357
function setStakeReward(
402358
address _account,
403359
uint96 _courtID,
404360
uint256 _reward
405361
) external override onlyByCore returns (bool success) {
406362
if (_reward == 0) return true; // No reward to add.
407363

408-
uint256 currentStake = stakeOf(_account, _courtID);
364+
uint256 currentStake = _stakeOf(_account, _courtID);
409365
if (currentStake == 0) return false; // Juror has been unstaked, don't increase their stake.
410366

411367
uint256 newStake = currentStake + _reward;
@@ -422,7 +378,7 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
422378
) internal {
423379
Juror storage juror = jurors[_account];
424380
if (_pnkDeposit > 0) {
425-
uint256 currentStake = stakeOf(_account, _courtID);
381+
uint256 currentStake = _stakeOf(_account, _courtID);
426382
if (currentStake == 0) {
427383
juror.courtIDs.push(_courtID);
428384
}
@@ -459,17 +415,13 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
459415
emit StakeSet(_account, _courtID, _newStake, juror.stakedPnk);
460416
}
461417

462-
/// @dev Locks the tokens of the drawn juror.
463-
/// @param _account The address of the juror.
464-
/// @param _relativeAmount The amount to lock.
418+
/// @inheritdoc ISortitionModule
465419
function lockStake(address _account, uint256 _relativeAmount) external override onlyByCore {
466420
jurors[_account].lockedPnk += _relativeAmount;
467421
emit StakeLocked(_account, _relativeAmount, false);
468422
}
469423

470-
/// @dev Unlocks the tokens of the drawn juror.
471-
/// @param _account The address of the juror.
472-
/// @param _relativeAmount The amount to unlock.
424+
/// @inheritdoc ISortitionModule
473425
function unlockStake(address _account, uint256 _relativeAmount) external override onlyByCore {
474426
Juror storage juror = jurors[_account];
475427
juror.lockedPnk -= _relativeAmount;
@@ -481,38 +433,20 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
481433
}
482434
}
483435

484-
/// @dev Unstakes the inactive juror from all courts.
485-
/// `O(n * (p * log_k(j)) )` where
486-
/// `n` is the number of courts the juror has staked in,
487-
/// `p` is the depth of the court tree,
488-
/// `k` is the minimum number of children per node of one of these courts' sortition sum tree,
489-
/// and `j` is the maximum number of jurors that ever staked in one of these courts simultaneously.
490-
/// @param _account The juror to unstake.
436+
/// @inheritdoc ISortitionModule
491437
function forcedUnstakeAllCourts(address _account) external override onlyByCore {
492438
uint96[] memory courtIDs = getJurorCourtIDs(_account);
493439
for (uint256 j = courtIDs.length; j > 0; j--) {
494440
core.setStakeBySortitionModule(_account, courtIDs[j - 1], 0);
495441
}
496442
}
497443

498-
/// @dev Unstakes the inactive juror from a specific court.
499-
/// `O(n * (p * log_k(j)) )` where
500-
/// `n` is the number of courts the juror has staked in,
501-
/// `p` is the depth of the court tree,
502-
/// `k` is the minimum number of children per node of one of these courts' sortition sum tree,
503-
/// and `j` is the maximum number of jurors that ever staked in one of these courts simultaneously.
504-
/// @param _account The juror to unstake.
505-
/// @param _courtID The ID of the court.
444+
/// @inheritdoc ISortitionModule
506445
function forcedUnstake(address _account, uint96 _courtID) external override onlyByCore {
507446
core.setStakeBySortitionModule(_account, _courtID, 0);
508447
}
509448

510-
/// @dev Gives back the locked PNKs in case the juror fully unstaked earlier.
511-
/// Note that since locked and staked PNK are async it is possible for the juror to have positive staked PNK balance
512-
/// while having 0 stake in courts and 0 locked tokens (eg. when the juror fully unstaked during dispute and later got his tokens unlocked).
513-
/// In this case the juror can use this function to withdraw the leftover tokens.
514-
/// Also note that if the juror has some leftover PNK while not fully unstaked he'll have to manually unstake from all courts to trigger this function.
515-
/// @param _account The juror whose PNK to withdraw.
449+
/// @inheritdoc ISortitionModule
516450
function withdrawLeftoverPNK(address _account) external override {
517451
// Can withdraw the leftover PNK if fully unstaked, has no tokens locked and has positive balance.
518452
// This withdrawal can't be triggered by calling setStake() in KlerosCore because current stake is technically 0, thus it is done via separate function.
@@ -527,15 +461,7 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
527461
// * Public Views * //
528462
// ************************************* //
529463

530-
/// @dev Draw an ID from a tree using a number.
531-
/// Note that this function reverts if the sum of all values in the tree is 0.
532-
/// @param _courtID The ID of the court.
533-
/// @param _coreDisputeID Index of the dispute in Kleros Core.
534-
/// @param _nonce Nonce to hash with random number.
535-
/// @return drawnAddress The drawn address.
536-
/// `O(k * log_k(n))` where
537-
/// `k` is the maximum number of children per node in the tree,
538-
/// and `n` is the maximum number of nodes ever appended.
464+
/// @inheritdoc ISortitionModule
539465
function draw(
540466
uint96 _courtID,
541467
uint256 _coreDisputeID,
@@ -547,23 +473,7 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
547473
(drawnAddress, fromSubcourtID) = sortitionSumTrees[key].draw(_coreDisputeID, _nonce, randomNumber);
548474
}
549475

550-
/// @dev Get the stake of a juror in a court.
551-
/// @param _juror The address of the juror.
552-
/// @param _courtID The ID of the court.
553-
/// @return value The stake of the juror in the court.
554-
function stakeOf(address _juror, uint96 _courtID) public view returns (uint256) {
555-
bytes32 stakePathID = SortitionTrees.toStakePathID(_juror, _courtID);
556-
TreeKey key = CourtID.wrap(_courtID).toTreeKey();
557-
return sortitionSumTrees[key].stakeOf(stakePathID);
558-
}
559-
560-
/// @dev Gets the balance of a juror in a court.
561-
/// @param _juror The address of the juror.
562-
/// @param _courtID The ID of the court.
563-
/// @return totalStakedPnk The total amount of tokens staked including locked tokens and penalty deductions. Equivalent to the effective stake in the General court.
564-
/// @return totalLocked The total amount of tokens locked in disputes.
565-
/// @return stakedInCourt The amount of tokens staked in the specified court including locked tokens and penalty deductions.
566-
/// @return nbCourts The number of courts the juror has directly staked in.
476+
/// @inheritdoc ISortitionModule
567477
function getJurorBalance(
568478
address _juror,
569479
uint96 _courtID
@@ -576,26 +486,21 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
576486
Juror storage juror = jurors[_juror];
577487
totalStakedPnk = juror.stakedPnk;
578488
totalLocked = juror.lockedPnk;
579-
stakedInCourt = stakeOf(_juror, _courtID);
489+
stakedInCourt = _stakeOf(_juror, _courtID);
580490
nbCourts = juror.courtIDs.length;
581491
}
582492

583-
/// @dev Gets the court identifiers where a specific `_juror` has staked.
584-
/// @param _juror The address of the juror.
493+
/// @inheritdoc ISortitionModule
585494
function getJurorCourtIDs(address _juror) public view override returns (uint96[] memory) {
586495
return jurors[_juror].courtIDs;
587496
}
588497

589-
/// @dev Checks if the juror is staked in any court.
590-
/// @param _juror The address of the juror.
591-
/// @return Whether the juror is staked or not.
498+
/// @inheritdoc ISortitionModule
592499
function isJurorStaked(address _juror) external view override returns (bool) {
593500
return jurors[_juror].stakedPnk > 0;
594501
}
595502

596-
/// @dev Checks if the juror has any leftover PNK in the contract.
597-
/// @param _juror The address of the juror.
598-
/// @return Whether the juror has leftover PNK.
503+
/// @inheritdoc ISortitionModule
599504
function getJurorLeftoverPNK(address _juror) public view override returns (uint256) {
600505
Juror storage juror = jurors[_juror];
601506
if (juror.courtIDs.length == 0 && juror.lockedPnk == 0) {
@@ -609,6 +514,16 @@ contract SortitionModule is ISortitionModule, Initializable, UUPSProxiable {
609514
// * Internal * //
610515
// ************************************* //
611516

517+
/// @dev Get the stake of a juror in a court.
518+
/// @param _juror The address of the juror.
519+
/// @param _courtID The ID of the court.
520+
/// @return value The stake of the juror in the court.
521+
function _stakeOf(address _juror, uint96 _courtID) internal view returns (uint256) {
522+
bytes32 stakePathID = SortitionTrees.toStakePathID(_juror, _courtID);
523+
TreeKey key = CourtID.wrap(_courtID).toTreeKey();
524+
return sortitionSumTrees[key].stakeOf(stakePathID);
525+
}
526+
612527
/// @dev Converts sortition extradata into K value of sortition tree.
613528
/// @param _extraData Sortition extra data.
614529
/// @return K The value of K.

0 commit comments

Comments
 (0)