Skip to content

Commit 482440b

Browse files
authored
Merge pull request #6 from kleros/review/hbarcelos
Review/hbarcelos
2 parents 7b0c1db + d683f1f commit 482440b

File tree

5 files changed

+34
-21
lines changed

5 files changed

+34
-21
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ MetaMask setup for Sokol:
1919
## Unstake
2020
1. Unstake from the Sokol general court.
2121
1. You can use `withdrawAndConvertToPNK()` [method](https://blockscout.com/poa/sokol/address/0xe64818D4e179926299596745BA7C20A3E4a87164/write-contract) to directly convert the Sokol Wrapped PNK into Kovan PNK. If you use this method, it is possible to set the receiver. On the Kovan chain, the tokens have to be claimed though. Go to the [token bridge](https://sokol-omnibridge.web.app/bridge), connect MetaMask with your Kovan account and claim your tokens.
22-
1. If you rather use the token bridge, call `withdraw()` [method](https://blockscout.com/poa/sokol/address/0xe64818D4e179926299596745BA7C20A3E4a87164/write-contract) instead. On the Kovan chain, the tokens have to be claimed though. Go to the [token bridge](https://sokol-omnibridge.web.app/bridge), connect MetaMask with your Kovan account and claim your tokens.
22+
1. If you rather use the token bridge, call `withdraw()` [method](https://blockscout.com/poa/sokol/address/0xe64818D4e179926299596745BA7C20A3E4a87164/write-contract) instead. Then go to the [token bridge](https://sokol-omnibridge.web.app/bridge) convert your tokens.

contracts/kleros/xKlerosLiquid.sol

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* https://contributing.kleros.io/smart-contract-workflow
33
* @authors: [@fnanni-0]
4-
* @reviewers: [@shalzz, @unknownunknown1, @MerlinEgalite]
4+
* @reviewers: [@shalzz*, @unknownunknown1*, @MerlinEgalite*, @hbarcelos]
55
* @auditors: []
66
* @bounties: []
77
* @deployments: []
@@ -13,7 +13,7 @@ pragma solidity ^0.4.24;
1313
import "openzeppelin-eth/contracts/zos-lib/Initializable.sol";
1414
import { TokenController } from "minimetoken/contracts/TokenController.sol";
1515
import { Arbitrator, Arbitrable } from "@kleros/kleros-interaction/contracts/standard/arbitration/Arbitrator.sol";
16-
import { WrappedPinakion as Pinakion } from "../tokens/WrappedPinakion.sol";
16+
import { WrappedPinakion } from "../tokens/WrappedPinakion.sol";
1717
import { IRandomAuRa } from "../interfaces/IRandomAuRa.sol";
1818

1919
import { SortitionSumTreeFactory } from "@kleros/kleros/contracts/data-structures/SortitionSumTreeFactory.sol";
@@ -134,12 +134,13 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
134134
event Draw(address indexed _address, uint indexed _disputeID, uint _appeal, uint _voteID);
135135

136136
/** @dev Emitted when a juror wins or loses tokens and xDai from a dispute.
137+
* The original name from KlerosLiquid is kept in this event to match its ABI.
137138
* @param _address The juror affected.
138139
* @param _disputeID The ID of the dispute.
139140
* @param _tokenAmount The amount of tokens won or lost.
140141
* @param _xDaiAmount The amount of xDai won or lost.
141142
*/
142-
event TokenAndXDaiShift(address indexed _address, uint indexed _disputeID, int _tokenAmount, int _xDaiAmount);
143+
event TokenAndETHShift(address indexed _address, uint indexed _disputeID, int _tokenAmount, int _xDaiAmount);
143144

144145
/* Storage */
145146

@@ -150,7 +151,7 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
150151
uint public constant ALPHA_DIVISOR = 1e4; // The number to divide `Court.alpha` by.
151152
// General Contracts
152153
address public governor; // The governor of the contract.
153-
Pinakion public pinakion; // The Pinakion token contract.
154+
WrappedPinakion public pinakion; // The Pinakion token contract.
154155
IRandomAuRa public RNGenerator; // The random number generator contract.
155156
// General Dynamic
156157
Phase public phase; // The current phase.
@@ -214,10 +215,11 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
214215
* @param _jurorsForCourtJump The `jurorsForCourtJump` property value of the general court.
215216
* @param _timesPerPeriod The `timesPerPeriod` property value of the general court.
216217
* @param _sortitionSumTreeK The number of children per node of the general court's sortition sum tree.
218+
* @param _maxTotalStakeAllowed The maximum amount of wrapped PNK that is allowed to be staked in this contract.
217219
*/
218220
function initialize(
219221
address _governor,
220-
Pinakion _pinakion,
222+
WrappedPinakion _pinakion,
221223
IRandomAuRa _RNGenerator,
222224
uint _minStakingTime,
223225
uint _maxDrawingTime,
@@ -227,7 +229,8 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
227229
uint _feeForJuror,
228230
uint _jurorsForCourtJump,
229231
uint[4] _timesPerPeriod,
230-
uint _sortitionSumTreeK
232+
uint _sortitionSumTreeK,
233+
uint _maxTotalStakeAllowed
231234
) public initializer {
232235
// Initialize contract.
233236
governor = _governor;
@@ -238,7 +241,7 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
238241
lastPhaseChange = now;
239242
lockInsolventTransfers = true;
240243
nextDelayedSetStake = 1;
241-
maxTotalStakeAllowed = 30 * 1e24; // 30 Million PNK.
244+
maxTotalStakeAllowed = _maxTotalStakeAllowed;
242245

243246
// Create the general court.
244247
courts.push(Court({
@@ -275,7 +278,7 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
275278
/** @dev Changes the `pinakion` storage variable.
276279
* @param _pinakion The new value for the `pinakion` storage variable.
277280
*/
278-
function changePinakion(Pinakion _pinakion) external onlyByGovernor {
281+
function changePinakion(WrappedPinakion _pinakion) external onlyByGovernor {
279282
pinakion = _pinakion;
280283
}
281284

@@ -468,6 +471,7 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
468471
}
469472

470473
/** @dev Executes the next delayed set stakes.
474+
* `O(n)` where `n` is the number of iterations to run.
471475
* @param _iterations The number of delayed set stakes to execute.
472476
*/
473477
function executeDelayedSetStakes(uint _iterations) external onlyDuringPhase(Phase.staking) {
@@ -580,12 +584,13 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
580584
}
581585

582586
/** @dev Computes the token and xDai rewards for a specified appeal in a specified dispute.
587+
* The original name from KlerosLiquid is kept in this function to match its ABI.
583588
* @param _disputeID The ID of the dispute.
584589
* @param _appeal The appeal.
585590
* @return tokenReward The token reward.
586591
* @return xDaiReward The xDai reward.
587592
*/
588-
function computeTokenAndXDaiRewards(uint _disputeID, uint _appeal) private view returns(uint tokenReward, uint xDaiReward) {
593+
function computeTokenAndETHRewards(uint _disputeID, uint _appeal) private view returns(uint tokenReward, uint xDaiReward) {
589594
Dispute storage dispute = disputes[_disputeID];
590595

591596
// Distribute penalties and arbitration fees.
@@ -637,7 +642,7 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
637642
if (end > dispute.votes[_appeal].length) end = dispute.votes[_appeal].length;
638643
} else {
639644
// We loop over the votes twice, first to collect penalties, and second to distribute them as rewards along with arbitration fees.
640-
(tokenReward, xDaiReward) = dispute.repartitionsInEachRound[_appeal] >= dispute.votes[_appeal].length ? computeTokenAndXDaiRewards(_disputeID, _appeal) : (0, 0); // Compute rewards if rewarding.
645+
(tokenReward, xDaiReward) = dispute.repartitionsInEachRound[_appeal] >= dispute.votes[_appeal].length ? computeTokenAndETHRewards(_disputeID, _appeal) : (0, 0); // Compute rewards if rewarding.
641646
if (end > dispute.votes[_appeal].length * 2) end = dispute.votes[_appeal].length * 2;
642647
}
643648
for (uint i = dispute.repartitionsInEachRound[_appeal]; i < end; i++) {
@@ -652,7 +657,7 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
652657
pinakion.transfer(vote.account, tokenReward);
653658
// Intentional use to avoid blocking.
654659
vote.account.send(xDaiReward); // solium-disable-line security/no-send
655-
emit TokenAndXDaiShift(vote.account, _disputeID, int(tokenReward), int(xDaiReward));
660+
emit TokenAndETHShift(vote.account, _disputeID, int(tokenReward), int(xDaiReward));
656661
jurors[vote.account].lockedTokens -= dispute.tokensAtStakePerJuror[_appeal];
657662
}
658663
} else { // Juror was inactive, or voted incoherently and it was not a tie.
@@ -661,7 +666,7 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
661666
// Penalize.
662667
uint penalty = dispute.tokensAtStakePerJuror[_appeal] > pinakion.balanceOf(vote.account) ? pinakion.balanceOf(vote.account) : dispute.tokensAtStakePerJuror[_appeal];
663668
pinakion.transferFrom(vote.account, this, penalty);
664-
emit TokenAndXDaiShift(vote.account, _disputeID, -int(penalty), 0);
669+
emit TokenAndETHShift(vote.account, _disputeID, -int(penalty), 0);
665670
penaltiesInRoundCache += penalty;
666671
jurors[vote.account].lockedTokens -= dispute.tokensAtStakePerJuror[_appeal];
667672

@@ -681,7 +686,7 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
681686
} else if (i + 1 < end) {
682687
// Compute rewards because we are going into rewarding.
683688
dispute.penaltiesInEachRound[_appeal] = penaltiesInRoundCache;
684-
(tokenReward, xDaiReward) = computeTokenAndXDaiRewards(_disputeID, _appeal);
689+
(tokenReward, xDaiReward) = computeTokenAndETHRewards(_disputeID, _appeal);
685690
}
686691
}
687692
}
@@ -767,7 +772,7 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
767772
emit NewPeriod(_disputeID, Period.evidence);
768773
}
769774

770-
/** @dev Called when `_owner` sends xDai to the MiniMe Token contract.
775+
/** @dev DEPRECATED. Called when `_owner` sends xDai to the Wrapped Token contract.
771776
* @param _owner The address that sent the xDai to create tokens.
772777
* @return allowed Whether the operation should be allowed or not.
773778
*/
@@ -896,7 +901,8 @@ contract xKlerosLiquid is Initializable, TokenController, Arbitrator {
896901

897902
/** If maxTotalStakeAllowed was reduced through governance,
898903
* totalStake could be greater than maxTotalStakeAllowed.
899-
* In such case allow unstaking. Always allow unstaking.
904+
* If this happens, removing stake is still allowed even if
905+
* totalStake is greater than maxTotalStakeAllowed afterwards.
900906
*/
901907
if ((totalStake - juror.stakedTokens + newTotalStake > maxTotalStakeAllowed) && (newTotalStake > juror.stakedTokens))
902908
return false; // Maximum PNK stake reached.

contracts/tokens/WrappedPinakion.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* https://contributing.kleros.io/smart-contract-workflow
33
* @authors: [@fnanni-0]
4-
* @reviewers: [@unknownunknown1, @MerlinEgalite]
4+
* @reviewers: [@unknownunknown1, @MerlinEgalite, @hbarcelos]
55
* @auditors: []
66
* @bounties: []
77
* @deployments: []

migrations/2_deploy_contracts.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ let xKlerosLiquidParams = {
3838
feeForJuror: web3.utils.toWei('40000000000000000','wei'),
3939
jurorsForCourtJump: 511,
4040
timesPerPeriod: [280800, 583200, 583200, 388800],
41-
sortitionSumTreeK: 2
41+
sortitionSumTreeK: 2,
42+
maxTotalStakeAllowed: web3.utils.toWei('30000000','ether')
4243
},
4344
"sokol-fork": {
4445
governor: null,
@@ -52,7 +53,8 @@ let xKlerosLiquidParams = {
5253
feeForJuror: web3.utils.toWei('40000000000000000','wei'),
5354
jurorsForCourtJump: 511,
5455
timesPerPeriod: [280800, 583200, 583200, 388800],
55-
sortitionSumTreeK: 2
56+
sortitionSumTreeK: 2,
57+
maxTotalStakeAllowed: web3.utils.toWei('30000000','ether')
5658
},
5759
"sokol": {
5860
governor: null,
@@ -66,7 +68,8 @@ let xKlerosLiquidParams = {
6668
feeForJuror: web3.utils.toWei('40000000000000000','wei'),
6769
jurorsForCourtJump: 511,
6870
timesPerPeriod: [280800, 583200, 583200, 388800],
69-
sortitionSumTreeK: 2
71+
sortitionSumTreeK: 2,
72+
maxTotalStakeAllowed: web3.utils.toWei('30000000','ether')
7073
}
7174
}
7275

@@ -106,6 +109,7 @@ module.exports = async function(deployer, network) {
106109
xKlerosLiquidParams[network].jurorsForCourtJump,
107110
xKlerosLiquidParams[network].timesPerPeriod,
108111
xKlerosLiquidParams[network].sortitionSumTreeK,
112+
xKlerosLiquidParams[network].maxTotalStakeAllowed,
109113
],
110114
{ deployer, unsafeAllowLinkedLibraries: true }
111115
);

test/kleros/kleros-liquid.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ contract('xKlerosLiquid', (accounts) => {
101101
let maxDrawingTime
102102
let subcourtTree
103103
let subcourtMap
104+
let maxTotalStakeAllowed
104105
let klerosLiquid
105106
beforeEach(async () => {
106107
governor = accounts[0]
@@ -126,6 +127,7 @@ contract('xKlerosLiquid', (accounts) => {
126127
} = generateSubcourts(randomInt(4, 2), 3)
127128
subcourtTree = _subcourtTree
128129
subcourtMap = _subcourtMap
130+
maxTotalStakeAllowed = web3.utils.toWei('30000000', 'ether') // 30M PNK
129131

130132
const sortitionSumTreeFactoryLib = await SortitionSumTreeFactory.new()
131133
await xKlerosLiquid.link(
@@ -147,6 +149,7 @@ contract('xKlerosLiquid', (accounts) => {
147149
subcourtTree.jurorsForJump,
148150
subcourtTree.timesPerPeriod,
149151
subcourtTree.sortitionSumTreeK,
152+
maxTotalStakeAllowed,
150153
],
151154
{ unsafeAllowLinkedLibraries: true }
152155
)
@@ -534,7 +537,7 @@ contract('xKlerosLiquid', (accounts) => {
534537
.mod(coherentVotes)
535538
expect(PNKBefore.eq(PNKAfter.add(burntPNK))).to.equal(true)
536539
const tokensShiftEvents = await klerosLiquid.getPastEvents(
537-
'TokenAndXDaiShift',
540+
'TokenAndETHShift',
538541
{
539542
filter: { _disputeID: dispute.ID },
540543
fromBlock: executeBlockNumber,

0 commit comments

Comments
 (0)