11// SPDX-License-Identifier: MIT
22
3- pragma solidity ^ 0.8.24 ;
3+ pragma solidity 0.8.24 ;
44
55import {IArbitrableV2, IArbitratorV2} from "./interfaces/IArbitratorV2.sol " ;
66import {IDisputeKit} from "./interfaces/IDisputeKit.sol " ;
77import {ISortitionModule} from "./interfaces/ISortitionModule.sol " ;
88import {Initializable} from "../proxy/Initializable.sol " ;
99import {UUPSProxiable} from "../proxy/UUPSProxiable.sol " ;
1010import {SafeERC20, IERC20 } from "../libraries/SafeERC20.sol " ;
11- import {WethLike, SafeSend} from "../libraries/SafeSend.sol " ;
11+ import {SafeSend} from "../libraries/SafeSend.sol " ;
1212import "../libraries/Constants.sol " ;
1313
1414/// @title KlerosCoreBase
@@ -192,7 +192,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
192192 // * Constructor * //
193193 // ************************************* //
194194
195- /**
195+ /**
196196 * @dev This contract is deployed only once per chain, as the logic master contract.
197197 * New instances are created with minimal proxy from the factory.
198198 * 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
201201 */
202202 constructor (address _wNative ) {
203203 W_NATIVE = _wNative;
204- }
204+ }
205205
206206 function __KlerosCoreBase_initialize (
207207 address _governor ,
@@ -213,7 +213,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
213213 uint256 [4 ] memory _courtParameters ,
214214 uint256 [4 ] memory _timesPerPeriod ,
215215 bytes memory _sortitionExtraData ,
216- ISortitionModule _sortitionModuleAddress ,
216+ ISortitionModule _sortitionModuleAddress
217217 ) internal onlyInitializing {
218218 governor = _governor;
219219 guardian = _guardian;
@@ -477,25 +477,22 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
477477 /// @param _newStake The new stake.
478478 /// Note that the existing delayed stake will be nullified as non-relevant.
479479 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);
481481 }
482482
483483 /// @dev Sets the stake of a specified account in a court, typically to apply a delayed stake or unstake inactive jurors.
484484 /// @param _account The account whose stake is being set.
485485 /// @param _courtID The ID of the court.
486486 /// @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 {
496494 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);
499496 }
500497
501498 /// @inheritdoc IArbitratorV2
@@ -791,25 +788,26 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
791788
792789 // Fully coherent jurors won't be penalized.
793790 uint256 penalty = (round.pnkAtStakePerJuror * (ALPHA_DIVISOR - degreeOfCoherence)) / ALPHA_DIVISOR;
791+ _params.pnkPenaltiesInRound += penalty;
794792
795793 // Unlock the PNKs affected by the penalty
796794 address account = round.drawnJurors[_params.repartition];
797795 sortitionModule.unlockStake (account, penalty);
798796
799797 // 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);
802799 emit TokenAndETHShift (
803800 account,
804801 _params.disputeID,
805802 _params.round,
806803 degreeOfCoherence,
807- - int256 (availablePenalty ),
804+ - int256 (penalty ),
808805 0 ,
809806 round.feeToken
810807 );
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.
813811 sortitionModule.setJurorInactive (account);
814812 }
815813 if (_params.repartition == _params.numberOfVotesInRound - 1 && _params.coherentCount == 0 ) {
@@ -860,6 +858,11 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
860858 // Release the rest of the PNKs of the juror for this round.
861859 sortitionModule.unlockStake (account, pnkLocked);
862860
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+
863866 // Transfer the rewards
864867 uint256 pnkReward = ((_params.pnkPenaltiesInRound / _params.coherentCount) * degreeOfCoherence) / ALPHA_DIVISOR;
865868 round.sumPnkRewardPaid += pnkReward;
@@ -1085,9 +1088,16 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
10851088 /// @param _account The account to set the stake for.
10861089 /// @param _courtID The ID of the court to set the stake for.
10871090 /// @param _newStake The new stake.
1091+ /// @param _alreadyTransferred Whether the PNKs were already transferred to/from the staking contract.
10881092 /// @param _onError Whether to revert or return false on error.
10891093 /// @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 ) {
10911101 if (_courtID == FORKING_COURT || _courtID >= courts.length ) {
10921102 _stakingFailed (_onError, StakingResult.CannotStakeInThisCourt); // Staking directly into the forking court is not allowed.
10931103 return false ;
@@ -1096,16 +1106,15 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
10961106 _stakingFailed (_onError, StakingResult.CannotStakeLessThanMinStake); // Staking less than the minimum stake is not allowed.
10971107 return false ;
10981108 }
1099- (uint256 pnkDeposit , uint256 pnkWithdrawal , StakingResult stakingResult ) = sortitionModule.validateStake (
1109+ (uint256 pnkDeposit , uint256 pnkWithdrawal , StakingResult stakingResult ) = sortitionModule.setStake (
11001110 _account,
11011111 _courtID,
1102- _newStake
1112+ _newStake,
1113+ _alreadyTransferred
11031114 );
1104- if (stakingResult != StakingResult.Successful && stakingResult != StakingResult.Delayed ) {
1115+ if (stakingResult != StakingResult.Successful) {
11051116 _stakingFailed (_onError, stakingResult);
11061117 return false ;
1107- } else if (stakingResult == StakingResult.Delayed) {
1108- return true ;
11091118 }
11101119 if (pnkDeposit > 0 ) {
11111120 if (! pinakion.safeTransferFrom (_account, address (this ), pnkDeposit)) {
@@ -1119,8 +1128,6 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
11191128 return false ;
11201129 }
11211130 }
1122- sortitionModule.setStake (_account, _courtID, pnkDeposit, pnkWithdrawal, _newStake);
1123-
11241131 return true ;
11251132 }
11261133
0 commit comments