1
1
// SPDX-License-Identifier: MIT
2
2
3
- pragma solidity ^ 0.8.24 ;
3
+ pragma solidity 0.8.24 ;
4
4
5
5
import {IArbitrableV2, IArbitratorV2} from "./interfaces/IArbitratorV2.sol " ;
6
6
import {IDisputeKit} from "./interfaces/IDisputeKit.sol " ;
7
7
import {ISortitionModule} from "./interfaces/ISortitionModule.sol " ;
8
8
import {Initializable} from "../proxy/Initializable.sol " ;
9
9
import {UUPSProxiable} from "../proxy/UUPSProxiable.sol " ;
10
10
import {SafeERC20, IERC20 } from "../libraries/SafeERC20.sol " ;
11
- import {WethLike, SafeSend} from "../libraries/SafeSend.sol " ;
11
+ import {SafeSend} from "../libraries/SafeSend.sol " ;
12
12
import "../libraries/Constants.sol " ;
13
13
14
14
/// @title KlerosCoreBase
@@ -192,7 +192,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
192
192
// * Constructor * //
193
193
// ************************************* //
194
194
195
- /**
195
+ /**
196
196
* @dev This contract is deployed only once per chain, as the logic master contract.
197
197
* New instances are created with minimal proxy from the factory.
198
198
* This is only needed to set the wrapped native token, which is used in SafeSend.
@@ -201,7 +201,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
201
201
*/
202
202
constructor (address _wNative ) {
203
203
W_NATIVE = _wNative;
204
- }
204
+ }
205
205
206
206
function __KlerosCoreBase_initialize (
207
207
address _governor ,
@@ -213,7 +213,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
213
213
uint256 [4 ] memory _courtParameters ,
214
214
uint256 [4 ] memory _timesPerPeriod ,
215
215
bytes memory _sortitionExtraData ,
216
- ISortitionModule _sortitionModuleAddress ,
216
+ ISortitionModule _sortitionModuleAddress
217
217
) internal onlyInitializing {
218
218
governor = _governor;
219
219
guardian = _guardian;
@@ -477,25 +477,22 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
477
477
/// @param _newStake The new stake.
478
478
/// Note that the existing delayed stake will be nullified as non-relevant.
479
479
function setStake (uint96 _courtID , uint256 _newStake ) external virtual whenNotPaused {
480
- _setStake (msg .sender , _courtID, _newStake, OnError.Revert);
480
+ _setStake (msg .sender , _courtID, _newStake, false , OnError.Revert);
481
481
}
482
482
483
483
/// @dev Sets the stake of a specified account in a court, typically to apply a delayed stake or unstake inactive jurors.
484
484
/// @param _account The account whose stake is being set.
485
485
/// @param _courtID The ID of the court.
486
486
/// @param _newStake The new stake.
487
- function setStakeBySortitionModule (address _account , uint96 _courtID , uint256 _newStake ) external {
488
- if (msg .sender != address (sortitionModule)) revert SortitionModuleOnly ();
489
- _setStake (_account, _courtID, _newStake, OnError.Return);
490
- }
491
-
492
- /// @dev Transfers PNK to the juror by SortitionModule.
493
- /// @param _account The account of the juror whose PNK to transfer.
494
- /// @param _amount The amount to transfer.
495
- function transferBySortitionModule (address _account , uint256 _amount ) external {
487
+ /// @param _alreadyTransferred Whether the PNKs have already been transferred to the contract.
488
+ function setStakeBySortitionModule (
489
+ address _account ,
490
+ uint96 _courtID ,
491
+ uint256 _newStake ,
492
+ bool _alreadyTransferred
493
+ ) external {
496
494
if (msg .sender != address (sortitionModule)) revert SortitionModuleOnly ();
497
- // Note eligibility is checked in SortitionModule.
498
- pinakion.safeTransfer (_account, _amount);
495
+ _setStake (_account, _courtID, _newStake, _alreadyTransferred, OnError.Return);
499
496
}
500
497
501
498
/// @inheritdoc IArbitratorV2
@@ -791,25 +788,26 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
791
788
792
789
// Fully coherent jurors won't be penalized.
793
790
uint256 penalty = (round.pnkAtStakePerJuror * (ALPHA_DIVISOR - degreeOfCoherence)) / ALPHA_DIVISOR;
791
+ _params.pnkPenaltiesInRound += penalty;
794
792
795
793
// Unlock the PNKs affected by the penalty
796
794
address account = round.drawnJurors[_params.repartition];
797
795
sortitionModule.unlockStake (account, penalty);
798
796
799
797
// Apply the penalty to the staked PNKs.
800
- (uint256 pnkBalance , uint256 availablePenalty ) = sortitionModule.penalizeStake (account, penalty);
801
- _params.pnkPenaltiesInRound += availablePenalty;
798
+ sortitionModule.penalizeStake (account, penalty);
802
799
emit TokenAndETHShift (
803
800
account,
804
801
_params.disputeID,
805
802
_params.round,
806
803
degreeOfCoherence,
807
- - int256 (availablePenalty ),
804
+ - int256 (penalty ),
808
805
0 ,
809
806
round.feeToken
810
807
);
811
- // Unstake the juror from all courts if he was inactive or his balance can't cover penalties anymore.
812
- if (pnkBalance == 0 || ! disputeKit.isVoteActive (_params.disputeID, _params.round, _params.repartition)) {
808
+
809
+ if (! disputeKit.isVoteActive (_params.disputeID, _params.round, _params.repartition)) {
810
+ // The juror is inactive, unstake them.
813
811
sortitionModule.setJurorInactive (account);
814
812
}
815
813
if (_params.repartition == _params.numberOfVotesInRound - 1 && _params.coherentCount == 0 ) {
@@ -860,6 +858,11 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
860
858
// Release the rest of the PNKs of the juror for this round.
861
859
sortitionModule.unlockStake (account, pnkLocked);
862
860
861
+ // Give back the locked PNKs in case the juror fully unstaked earlier.
862
+ if (! sortitionModule.isJurorStaked (account)) {
863
+ pinakion.safeTransfer (account, pnkLocked);
864
+ }
865
+
863
866
// Transfer the rewards
864
867
uint256 pnkReward = ((_params.pnkPenaltiesInRound / _params.coherentCount) * degreeOfCoherence) / ALPHA_DIVISOR;
865
868
round.sumPnkRewardPaid += pnkReward;
@@ -1085,9 +1088,16 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
1085
1088
/// @param _account The account to set the stake for.
1086
1089
/// @param _courtID The ID of the court to set the stake for.
1087
1090
/// @param _newStake The new stake.
1091
+ /// @param _alreadyTransferred Whether the PNKs were already transferred to/from the staking contract.
1088
1092
/// @param _onError Whether to revert or return false on error.
1089
1093
/// @return Whether the stake was successfully set or not.
1090
- function _setStake (address _account , uint96 _courtID , uint256 _newStake , OnError _onError ) internal returns (bool ) {
1094
+ function _setStake (
1095
+ address _account ,
1096
+ uint96 _courtID ,
1097
+ uint256 _newStake ,
1098
+ bool _alreadyTransferred ,
1099
+ OnError _onError
1100
+ ) internal returns (bool ) {
1091
1101
if (_courtID == FORKING_COURT || _courtID >= courts.length ) {
1092
1102
_stakingFailed (_onError, StakingResult.CannotStakeInThisCourt); // Staking directly into the forking court is not allowed.
1093
1103
return false ;
@@ -1096,16 +1106,15 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
1096
1106
_stakingFailed (_onError, StakingResult.CannotStakeLessThanMinStake); // Staking less than the minimum stake is not allowed.
1097
1107
return false ;
1098
1108
}
1099
- (uint256 pnkDeposit , uint256 pnkWithdrawal , StakingResult stakingResult ) = sortitionModule.validateStake (
1109
+ (uint256 pnkDeposit , uint256 pnkWithdrawal , StakingResult stakingResult ) = sortitionModule.setStake (
1100
1110
_account,
1101
1111
_courtID,
1102
- _newStake
1112
+ _newStake,
1113
+ _alreadyTransferred
1103
1114
);
1104
- if (stakingResult != StakingResult.Successful && stakingResult != StakingResult.Delayed ) {
1115
+ if (stakingResult != StakingResult.Successful) {
1105
1116
_stakingFailed (_onError, stakingResult);
1106
1117
return false ;
1107
- } else if (stakingResult == StakingResult.Delayed) {
1108
- return true ;
1109
1118
}
1110
1119
if (pnkDeposit > 0 ) {
1111
1120
if (! pinakion.safeTransferFrom (_account, address (this ), pnkDeposit)) {
@@ -1119,8 +1128,6 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
1119
1128
return false ;
1120
1129
}
1121
1130
}
1122
- sortitionModule.setStake (_account, _courtID, pnkDeposit, pnkWithdrawal, _newStake);
1123
-
1124
1131
return true ;
1125
1132
}
1126
1133
0 commit comments