@@ -483,14 +483,14 @@ contract KlerosCore is IArbitratorV2 {
483483
484484 /// @dev Sets the caller's stake in a court.
485485 /// @param _courtID The ID of the court.
486- /// @param _stake The new stake.
487- function setStake (uint96 _courtID , uint256 _stake ) external {
488- if (! _setStakeForAccount (msg .sender , _courtID, _stake )) revert StakingFailed ();
486+ /// @param _newStake The new stake.
487+ function setStake (uint96 _courtID , uint256 _newStake ) external {
488+ if (! _setStakeForAccount (msg .sender , _courtID, _newStake )) revert StakingFailed ();
489489 }
490490
491- function setStakeBySortitionModule (address _account , uint96 _courtID , uint256 _stake ) external {
491+ function setStakeBySortitionModule (address _account , uint96 _courtID , uint256 _newStake ) external {
492492 if (msg .sender != address (sortitionModule)) revert WrongCaller ();
493- _setStakeForAccount (_account, _courtID, _stake );
493+ _setStakeForAccount (_account, _courtID, _newStake );
494494 }
495495
496496 /// @inheritdoc IArbitratorV2
@@ -611,17 +611,16 @@ contract KlerosCore is IArbitratorV2 {
611611 IDisputeKit disputeKit = disputeKitNodes[round.disputeKitID].disputeKit;
612612
613613 uint256 startIndex = round.drawIterations;
614- // TODO: cap the iterations?
615- for (uint256 i = startIndex; i < startIndex + _iterations; i++ ) {
614+ for (uint256 i = startIndex; i < startIndex + _iterations && round.drawnJurors.length < round.nbVotes; i++ ) {
616615 address drawnAddress = disputeKit.draw (_disputeID, i);
617- if (drawnAddress ! = address (0 )) {
618- jurors[drawnAddress].lockedPnk += round.pnkAtStakePerJuror ;
619- emit Draw (drawnAddress, _disputeID, currentRound, round.drawnJurors. length );
620- round.drawnJurors. push (drawnAddress) ;
621-
622- if ( round.drawnJurors.length == round.nbVotes) {
623- sortitionModule. postDrawHook (_disputeID, currentRound);
624- }
616+ if (drawnAddress = = address (0 )) {
617+ continue ;
618+ }
619+ jurors[drawnAddress].lockedPnk += round.pnkAtStakePerJuror ;
620+ emit Draw (drawnAddress, _disputeID, currentRound, round.drawnJurors. length );
621+ round.drawnJurors.push (drawnAddress);
622+ if (round.drawnJurors. length == round.nbVotes) {
623+ sortitionModule. postDrawHook (_disputeID, currentRound);
625624 }
626625 }
627626 round.drawIterations += _iterations;
@@ -1110,35 +1109,40 @@ contract KlerosCore is IArbitratorV2 {
11101109 /// and `j` is the maximum number of jurors that ever staked in one of these courts simultaneously.
11111110 /// @param _account The address of the juror.
11121111 /// @param _courtID The ID of the court.
1113- /// @param _stake The new stake.
1112+ /// @param _newStake The new stake.
11141113 /// @return succeeded True if the call succeeded, false otherwise.
1115- function _setStakeForAccount (address _account , uint96 _courtID , uint256 _stake ) internal returns (bool succeeded ) {
1114+ function _setStakeForAccount (
1115+ address _account ,
1116+ uint96 _courtID ,
1117+ uint256 _newStake
1118+ ) internal returns (bool succeeded ) {
11161119 if (_courtID == FORKING_COURT || _courtID > courts.length ) return false ;
11171120
11181121 Juror storage juror = jurors[_account];
11191122 uint256 currentStake = juror.stakedPnkByCourt[_courtID];
11201123
1121- if (_stake != 0 ) {
1122- if (_stake < courts[_courtID].minStake) return false ;
1124+ if (_newStake != 0 ) {
1125+ if (_newStake < courts[_courtID].minStake) return false ;
11231126 } else if (currentStake == 0 ) {
11241127 return false ;
11251128 }
11261129
1127- ISortitionModule.preStakeHookResult result = sortitionModule.preStakeHook (_account, _courtID, _stake );
1130+ ISortitionModule.preStakeHookResult result = sortitionModule.preStakeHook (_account, _courtID, _newStake );
11281131 if (result == ISortitionModule.preStakeHookResult.failed) {
11291132 return false ;
11301133 } else if (result == ISortitionModule.preStakeHookResult.delayed) {
1131- emit StakeDelayed (_account, _courtID, _stake );
1134+ emit StakeDelayed (_account, _courtID, _newStake );
11321135 return true ;
11331136 }
11341137
11351138 uint256 transferredAmount;
1136- if (_stake >= currentStake) {
1139+ if (_newStake >= currentStake) {
1140+ // Stake increase
11371141 // When stakedPnk becomes lower than lockedPnk count the locked tokens in when transferring tokens from juror.
11381142 // (E.g. stakedPnk = 0, lockedPnk = 150) which can happen if the juror unstaked fully while having some tokens locked.
1139- uint256 previouslyLocked = (juror.lockedPnk >= juror.stakedPnk) ? juror.lockedPnk - juror.stakedPnk : 0 ;
1140- transferredAmount = (_stake >= currentStake + previouslyLocked)
1141- ? _stake - currentStake - previouslyLocked
1143+ uint256 previouslyLocked = (juror.lockedPnk >= juror.stakedPnk) ? juror.lockedPnk - juror.stakedPnk : 0 ; // underflow guard
1144+ transferredAmount = (_newStake >= currentStake + previouslyLocked) // underflow guard
1145+ ? _newStake - currentStake - previouslyLocked
11421146 : 0 ;
11431147 if (transferredAmount > 0 ) {
11441148 if (! pinakion.safeTransferFrom (_account, address (this ), transferredAmount)) {
@@ -1149,49 +1153,36 @@ contract KlerosCore is IArbitratorV2 {
11491153 juror.courtIDs.push (_courtID);
11501154 }
11511155 } else {
1152- if (_stake == 0 ) {
1153- // Make sure locked tokens always stay in the contract. They can only be released during Execution.
1154- if (juror.stakedPnk >= currentStake + juror.lockedPnk) {
1155- // We have enough pnk staked to afford withdrawal of the current stake while keeping locked tokens.
1156- transferredAmount = currentStake;
1157- } else if (juror.stakedPnk >= juror.lockedPnk) {
1158- // Can't afford withdrawing the current stake fully. Take whatever is available while keeping locked tokens.
1159- transferredAmount = juror.stakedPnk - juror.lockedPnk;
1160- }
1161- if (transferredAmount > 0 ) {
1162- if (! pinakion.safeTransfer (_account, transferredAmount)) {
1163- return false ;
1164- }
1156+ // Stake decrease: make sure locked tokens always stay in the contract. They can only be released during Execution.
1157+ if (juror.stakedPnk >= currentStake - _newStake + juror.lockedPnk) {
1158+ // We have enough pnk staked to afford withdrawal while keeping locked tokens.
1159+ transferredAmount = currentStake - _newStake;
1160+ } else if (juror.stakedPnk >= juror.lockedPnk) {
1161+ // Can't afford withdrawing the current stake fully. Take whatever is available while keeping locked tokens.
1162+ transferredAmount = juror.stakedPnk - juror.lockedPnk;
1163+ }
1164+ if (transferredAmount > 0 ) {
1165+ if (! pinakion.safeTransfer (_account, transferredAmount)) {
1166+ return false ;
11651167 }
1168+ }
1169+ if (_newStake == 0 ) {
11661170 for (uint256 i = juror.courtIDs.length ; i > 0 ; i-- ) {
11671171 if (juror.courtIDs[i - 1 ] == _courtID) {
11681172 juror.courtIDs[i - 1 ] = juror.courtIDs[juror.courtIDs.length - 1 ];
11691173 juror.courtIDs.pop ();
11701174 break ;
11711175 }
11721176 }
1173- } else {
1174- if (juror.stakedPnk >= currentStake - _stake + juror.lockedPnk) {
1175- // We have enough pnk staked to afford withdrawal while keeping locked tokens.
1176- transferredAmount = currentStake - _stake;
1177- } else if (juror.stakedPnk >= juror.lockedPnk) {
1178- // Can't afford withdrawing the current stake fully. Take whatever is available while keeping locked tokens.
1179- transferredAmount = juror.stakedPnk - juror.lockedPnk;
1180- }
1181- if (transferredAmount > 0 ) {
1182- if (! pinakion.safeTransfer (_account, transferredAmount)) {
1183- return false ;
1184- }
1185- }
11861177 }
11871178 }
11881179
11891180 // Note that stakedPnk can become async with currentStake (e.g. after penalty).
1190- juror.stakedPnk = (juror.stakedPnk >= currentStake) ? juror.stakedPnk - currentStake + _stake : _stake ;
1191- juror.stakedPnkByCourt[_courtID] = _stake ;
1181+ juror.stakedPnk = (juror.stakedPnk >= currentStake) ? juror.stakedPnk - currentStake + _newStake : _newStake ;
1182+ juror.stakedPnkByCourt[_courtID] = _newStake ;
11921183
1193- sortitionModule.setStake (_account, _courtID, _stake );
1194- emit StakeSet (_account, _courtID, _stake );
1184+ sortitionModule.setStake (_account, _courtID, _newStake );
1185+ emit StakeSet (_account, _courtID, _newStake );
11951186 return true ;
11961187 }
11971188
0 commit comments