From 10bcccf4b27e39980e2d679c2f70f27dad695ea0 Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Wed, 17 Mar 2021 11:27:56 +0700 Subject: [PATCH 01/11] fix: use fixed reward precision again --- contracts/staking/validatorShare/ValidatorShare.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index a4e37ad08..99ca9f3fc 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -20,6 +20,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I // maximum matic possible, even if rate will be 1 and all matic will be staken in one go, it will result in 10 ^ 58 shares uint256 constant EXCHANGE_RATE_HIGH_PRECISION = 10**29; uint256 constant MAX_COMMISION_RATE = 100; + uint256 constant REWARD_PRECISION = 10**25; StakingInfo public stakingLogger; IStakeManager public stakeManager; @@ -321,7 +322,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I uint256 totalShares = totalSupply(); if (totalShares != 0) { - _rewardPerShare = _rewardPerShare.add(accumulatedReward.mul(_getRatePrecision()).div(totalShares)); + _rewardPerShare = _rewardPerShare.add(accumulatedReward.mul(REWARD_PRECISION).div(totalShares)); } } @@ -340,7 +341,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return 0; } - return _rewardPerShare.sub(_initialRewardPerShare).mul(shares).div(_getRatePrecision()); + return _rewardPerShare.sub(_initialRewardPerShare).mul(shares).div(REWARD_PRECISION); } function _withdrawReward(address user) private returns (uint256) { From 43469ea76102497d23c49bc14f226a3008a4d05d Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Wed, 17 Mar 2021 11:33:45 +0700 Subject: [PATCH 02/11] chg: emit corresponding event while claiming stake --- contracts/staking/EventsHub.sol | 22 ++++++++++++++++--- .../staking/validatorShare/ValidatorShare.sol | 11 ++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/contracts/staking/EventsHub.sol b/contracts/staking/EventsHub.sol index f49fc9db7..55fac104d 100644 --- a/contracts/staking/EventsHub.sol +++ b/contracts/staking/EventsHub.sol @@ -42,7 +42,7 @@ contract EventsHub is Initializable { address indexed user, uint256 indexed amount, uint256 tokens, - uint256 burnId + uint256 nonce ); function logShareBurnedWithId( @@ -50,9 +50,25 @@ contract EventsHub is Initializable { address user, uint256 amount, uint256 tokens, - uint256 burnId + uint256 nonce ) public onlyValidatorContract(validatorId) { - emit ShareBurnedWithId(validatorId, user, amount, tokens, burnId); + emit ShareBurnedWithId(validatorId, user, amount, tokens, nonce); + } + + event DelegatorUnstakeWithId( + uint256 indexed validatorId, + address indexed user, + uint256 amount, + uint256 nonce + ); + + function logDelegatorUnstakedWithIdId( + uint256 validatorId, + address user, + uint256 amount, + uint256 nonce + ) public onlyValidatorContract(validatorId) { + emit DelegatorUnstakeWithId(validatorId, user, amount, nonce); } event RewardParams( diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 99ca9f3fc..3fe21f21b 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -187,8 +187,9 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I function unstakeClaimTokens() public { DelegatorUnbond memory unbond = unbonds[msg.sender]; - _unstakeClaimTokens(unbond); + uint256 amount = _unstakeClaimTokens(unbond); delete unbonds[msg.sender]; + stakingLogger.logDelegatorUnstaked(validatorId, msg.sender, amount); } function slash( @@ -252,8 +253,9 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I function unstakeClaimTokens_new(uint256 unbondNonce) public { DelegatorUnbond memory unbond = unbonds_new[msg.sender][unbondNonce]; - _unstakeClaimTokens(unbond); + uint256 amount = _unstakeClaimTokens(unbond); delete unbonds_new[msg.sender][unbondNonce]; + _getOrCacheEventsHub().logDelegatorUnstakedWithIdId(validatorId, msg.sender, amount, unbondNonce); } /** @@ -292,7 +294,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return (shares, _withdrawPoolShare); } - function _unstakeClaimTokens(DelegatorUnbond memory unbond) private { + function _unstakeClaimTokens(DelegatorUnbond memory unbond) private returns(uint256) { uint256 shares = unbond.shares; require( unbond.withdrawEpoch.add(stakeManager.withdrawalDelay()) <= stakeManager.epoch() && shares > 0, @@ -304,7 +306,8 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I withdrawPool = withdrawPool.sub(_amount); require(stakeManager.transferFunds(validatorId, _amount, msg.sender), "Insufficent rewards"); - stakingLogger.logDelegatorUnstaked(validatorId, msg.sender, _amount); + + return _amount; } function _getRatePrecision() private view returns (uint256) { From bf853f3f487d921332fa58248d015fc5b34379f4 Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Wed, 17 Mar 2021 12:33:49 +0700 Subject: [PATCH 03/11] misc: typo --- contracts/staking/EventsHub.sol | 2 +- contracts/staking/validatorShare/ValidatorShare.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/staking/EventsHub.sol b/contracts/staking/EventsHub.sol index 55fac104d..b38f2fabd 100644 --- a/contracts/staking/EventsHub.sol +++ b/contracts/staking/EventsHub.sol @@ -62,7 +62,7 @@ contract EventsHub is Initializable { uint256 nonce ); - function logDelegatorUnstakedWithIdId( + function logDelegatorUnstakedWithId( uint256 validatorId, address user, uint256 amount, diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 3fe21f21b..f9c10e460 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -255,7 +255,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I DelegatorUnbond memory unbond = unbonds_new[msg.sender][unbondNonce]; uint256 amount = _unstakeClaimTokens(unbond); delete unbonds_new[msg.sender][unbondNonce]; - _getOrCacheEventsHub().logDelegatorUnstakedWithIdId(validatorId, msg.sender, amount, unbondNonce); + _getOrCacheEventsHub().logDelegatorUnstakedWithId(validatorId, msg.sender, amount, unbondNonce); } /** From 823e13a30e2dac0d84723b6d539dd92e860885a2 Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Mon, 22 Mar 2021 15:59:01 +0700 Subject: [PATCH 04/11] fix: test --- test/units/staking/ValidatorShare.test.js | 24 ++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/test/units/staking/ValidatorShare.test.js b/test/units/staking/ValidatorShare.test.js index aea3c512f..3a599afc8 100644 --- a/test/units/staking/ValidatorShare.test.js +++ b/test/units/staking/ValidatorShare.test.js @@ -750,7 +750,7 @@ contract('ValidatorShare', async function() { userTotalStaked, totalStaked, shares, - burnId, + nonce, withdrawalExchangeRate = ExchangeRatePrecision }) { if (minClaimAmount) { @@ -763,14 +763,14 @@ contract('ValidatorShare', async function() { }) } - if (burnId) { + if (nonce) { it('must emit ShareBurnedWithId', async function() { await expectEvent.inTransaction(this.receipt.tx, EventsHub, 'ShareBurnedWithId', { validatorId: validatorId, tokens: shares, amount: returnedStake, user: user, - burnId + nonce }) }) } else { @@ -1006,7 +1006,7 @@ contract('ValidatorShare', async function() { validatorId: '8', user: Alice, userTotalStaked: halfStake, - burnId: '1', + nonce: '1', totalStaked: halfStake.add(ValidatorDefaultStake) }) }) @@ -1025,7 +1025,7 @@ contract('ValidatorShare', async function() { validatorId: '8', user: Alice, userTotalStaked: '0', - burnId: '2', + nonce: '2', totalStaked: ValidatorDefaultStake }) }) @@ -1049,7 +1049,7 @@ contract('ValidatorShare', async function() { initialBalance: new BN(0), validatorId: '8', user: Alice, - burnId: '1', + nonce: '1', userTotalStaked: halfStake, totalStaked: halfStake.add(validatorHalfStake) }) @@ -1069,7 +1069,7 @@ contract('ValidatorShare', async function() { validatorId: '8', user: Alice, userTotalStaked: '0', - burnId: '2', + nonce: '2', totalStaked: validatorHalfStake }) }) @@ -1785,11 +1785,12 @@ contract('ValidatorShare', async function() { }) }) - it('must emit DelegatorUnstaked', async function() { + it('must emit DelegatorUnstakeWithId', async function() { await expectEvent.inTransaction(this.receipt.tx, StakingInfo, 'DelegatorUnstaked', { validatorId: this.validatorId, user: this.user, - amount: this.claimAmount + amount: this.claimAmount, + nonce: '1' }) }) @@ -1799,11 +1800,12 @@ contract('ValidatorShare', async function() { }) }) - it('must emit DelegatorUnstaked', async function() { + it('must emit DelegatorUnstakeWithId', async function() { await expectEvent.inTransaction(this.receipt.tx, StakingInfo, 'DelegatorUnstaked', { validatorId: this.validatorId, user: this.user, - amount: this.claimAmount + amount: this.claimAmount, + nonce: '2' }) }) From 0d2d4eafb99c77238760b7ebb7130a31d68d1fbe Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Tue, 23 Mar 2021 19:48:50 +0700 Subject: [PATCH 05/11] fix: test --- test/units/staking/ValidatorShare.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/units/staking/ValidatorShare.test.js b/test/units/staking/ValidatorShare.test.js index 3a599afc8..dacf27e62 100644 --- a/test/units/staking/ValidatorShare.test.js +++ b/test/units/staking/ValidatorShare.test.js @@ -1786,7 +1786,7 @@ contract('ValidatorShare', async function() { }) it('must emit DelegatorUnstakeWithId', async function() { - await expectEvent.inTransaction(this.receipt.tx, StakingInfo, 'DelegatorUnstaked', { + await expectEvent.inTransaction(this.receipt.tx, StakingInfo, 'DelegatorUnstakeWithId', { validatorId: this.validatorId, user: this.user, amount: this.claimAmount, @@ -1801,7 +1801,7 @@ contract('ValidatorShare', async function() { }) it('must emit DelegatorUnstakeWithId', async function() { - await expectEvent.inTransaction(this.receipt.tx, StakingInfo, 'DelegatorUnstaked', { + await expectEvent.inTransaction(this.receipt.tx, StakingInfo, 'DelegatorUnstakeWithId', { validatorId: this.validatorId, user: this.user, amount: this.claimAmount, From 37bc88e6deff36d450a426c78942fd19c5f9f762 Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Tue, 23 Mar 2021 20:45:48 +0700 Subject: [PATCH 06/11] chg: pass commission rate into auction and stakeFor to avoid extra tx --- .../staking/stakeManager/IStakeManager.sol | 3 ++ .../staking/stakeManager/StakeManager.sol | 23 ++++++---- .../stakeManager/StakeManagerExtension.sol | 5 +++ .../stakeManager/StakeManagerStorage.sol | 1 + .../staking/validatorShare/ValidatorShare.sol | 2 +- test/units/staking/deployment.js | 4 +- .../stakeManager/StakeManager.Staking.js | 35 ++++++++++++--- .../staking/stakeManager/StakeManager.test.js | 44 +++++++++++++------ 8 files changed, 86 insertions(+), 31 deletions(-) diff --git a/contracts/staking/stakeManager/IStakeManager.sol b/contracts/staking/stakeManager/IStakeManager.sol index 867030fca..9dae193a0 100644 --- a/contracts/staking/stakeManager/IStakeManager.sol +++ b/contracts/staking/stakeManager/IStakeManager.sol @@ -5,6 +5,7 @@ contract IStakeManager { function startAuction( uint256 validatorId, uint256 amount, + uint256 commissionRate, bool acceptDelegation, bytes calldata signerPubkey ) external; @@ -31,6 +32,7 @@ contract IStakeManager { address user, uint256 amount, uint256 heimdallFee, + uint256 commissionRate, bool acceptDelegation, bytes memory signerPubkey ) public; @@ -70,6 +72,7 @@ contract IStakeManager { uint256 heimdallFee, uint256 validatorId, uint256 auctionAmount, + uint256 commissionRate, bool acceptDelegation, bytes calldata signerPubkey ) external; diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 22deda6d8..086edff54 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -352,8 +352,9 @@ contract StakeManager is function startAuction( uint256 validatorId, uint256 amount, - bool _acceptDelegation, - bytes calldata _signerPubkey + uint256 commissionRate, + bool acceptDelegation, + bytes calldata signerPubkey ) external onlyWhenUnlocked { delegatedFwd( extensionCode, @@ -361,8 +362,9 @@ contract StakeManager is StakeManagerExtension(extensionCode).startAuction.selector, validatorId, amount, - _acceptDelegation, - _signerPubkey + commissionRate, + acceptDelegation, + signerPubkey ) ); } @@ -387,6 +389,7 @@ contract StakeManager is uint256 heimdallFee, uint256 validatorId, uint256 auctionAmount, + uint256 commissionRate, bool acceptDelegation, bytes calldata signerPubkey ) external { @@ -395,7 +398,7 @@ contract StakeManager is _transferAndTopUp(auctionUser, auctionUser, heimdallFee, 0); _unstake(validatorId, currentEpoch); - uint256 newValidatorId = _stakeFor(auctionUser, auctionAmount, acceptDelegation, signerPubkey); + uint256 newValidatorId = _stakeFor(auctionUser, auctionAmount, commissionRate, acceptDelegation, signerPubkey); logger.logConfirmAuction(newValidatorId, validatorId, auctionAmount); } @@ -438,13 +441,14 @@ contract StakeManager is address user, uint256 amount, uint256 heimdallFee, + uint256 commissionRate, bool acceptDelegation, bytes memory signerPubkey ) public onlyWhenUnlocked { require(currentValidatorSetSize() < validatorThreshold, "no more slots"); require(amount >= minDeposit, "not enough deposit"); _transferAndTopUp(user, msg.sender, heimdallFee, amount); - _stakeFor(user, amount, acceptDelegation, signerPubkey); + _stakeFor(user, amount, commissionRate, acceptDelegation, signerPubkey); } function unstakeClaim(uint256 validatorId) public onlyStaker(validatorId) { @@ -1046,9 +1050,12 @@ contract StakeManager is function _stakeFor( address user, uint256 amount, + uint256 commissionRate, bool acceptDelegation, bytes memory signerPubkey ) internal returns (uint256) { + require(commissionRate <= MAX_COMMISION_RATE, "Incorrect value"); + address signer = _getAndAssertSigner(signerPubkey); uint256 _currentEpoch = currentEpoch; uint256 validatorId = NFTCounter; @@ -1068,8 +1075,8 @@ contract StakeManager is ? validatorShareFactory.create(validatorId, address(_logger), registry) : address(0x0), status: Status.Active, - commissionRate: 0, - lastCommissionUpdate: 0, + commissionRate: commissionRate, + lastCommissionUpdate: _currentEpoch, // commission rate was set explicitly delegatorsReward: INITIALIZED_AMOUNT, delegatedAmount: 0, initialRewardPerStake: rewardPerStake diff --git a/contracts/staking/stakeManager/StakeManagerExtension.sol b/contracts/staking/stakeManager/StakeManagerExtension.sol index c74dbcca4..bab10d420 100644 --- a/contracts/staking/stakeManager/StakeManagerExtension.sol +++ b/contracts/staking/stakeManager/StakeManagerExtension.sol @@ -20,11 +20,14 @@ contract StakeManagerExtension is StakeManagerStorage, Initializable, StakeManag function startAuction( uint256 validatorId, uint256 amount, + uint256 commissionRate, bool _acceptDelegation, bytes calldata _signerPubkey ) external { uint256 currentValidatorAmount = validators[validatorId].amount; + require(commissionRate <= MAX_COMMISION_RATE, "Incorrect value"); + require( validators[validatorId].deactivationEpoch == 0 && currentValidatorAmount != 0, "Invalid validator for an auction" @@ -72,6 +75,7 @@ contract StakeManagerExtension is StakeManagerStorage, Initializable, StakeManag // create new auction auction.amount = amount; auction.user = msg.sender; + auction.commissionRate = commissionRate; auction.acceptDelegation = _acceptDelegation; auction.signerPubkey = _signerPubkey; @@ -116,6 +120,7 @@ contract StakeManagerExtension is StakeManagerStorage, Initializable, StakeManag heimdallFee, validatorId, auctionAmount, + auction.commissionRate, auction.acceptDelegation, auction.signerPubkey ); diff --git a/contracts/staking/stakeManager/StakeManagerStorage.sol b/contracts/staking/stakeManager/StakeManagerStorage.sol index 6b448a838..d30bd3fd3 100644 --- a/contracts/staking/stakeManager/StakeManagerStorage.sol +++ b/contracts/staking/stakeManager/StakeManagerStorage.sol @@ -15,6 +15,7 @@ contract StakeManagerStorage is GovernanceLockable, RootChainable { struct Auction { uint256 amount; uint256 startEpoch; + uint256 commissionRate; address user; bool acceptDelegation; bytes signerPubkey; diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index f9c10e460..eda5ec4f9 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -86,7 +86,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I function withdrawExchangeRate() public view returns (uint256) { uint256 precision = _getRatePrecision(); - if (validatorId < 8) { + if (validatorId < 9) { // fix of potentially broken withdrawals for future unbonding // foundation validators have no slashing enabled and thus we can return default exchange rate // because without slashing rate will stay constant diff --git a/test/units/staking/deployment.js b/test/units/staking/deployment.js index f6a1ca53f..02481b5d2 100644 --- a/test/units/staking/deployment.js +++ b/test/units/staking/deployment.js @@ -60,7 +60,7 @@ export async function freshDeploy() { this.defaultHeimdallFee = new BN(web3.utils.toWei('1')) } -export async function approveAndStake({ wallet, stakeAmount, approveAmount, acceptDelegation = false, heimdallFee, noMinting = false, signer }) { +export async function approveAndStake({ wallet, stakeAmount, approveAmount, acceptDelegation = false, heimdallFee, noMinting = false, signer, commissionRate = 0 }) { const fee = heimdallFee || this.defaultHeimdallFee const mintAmount = new BN(approveAmount || stakeAmount).add(new BN(fee)) @@ -80,7 +80,7 @@ export async function approveAndStake({ wallet, stakeAmount, approveAmount, acce from: wallet.getAddressString() }) - await this.stakeManager.stakeFor(wallet.getAddressString(), stakeAmount, fee, acceptDelegation, signer || wallet.getPublicKeyString(), { + await this.stakeManager.stakeFor(wallet.getAddressString(), stakeAmount, fee, commissionRate, acceptDelegation, signer || wallet.getPublicKeyString(), { from: wallet.getAddressString() }) } diff --git a/test/units/staking/stakeManager/StakeManager.Staking.js b/test/units/staking/stakeManager/StakeManager.Staking.js index a753b86b0..1ac7898d7 100644 --- a/test/units/staking/stakeManager/StakeManager.Staking.js +++ b/test/units/staking/stakeManager/StakeManager.Staking.js @@ -1,8 +1,9 @@ -import { StakingInfo, TestToken, ValidatorShare } from '../../../helpers/artifacts' +import { StakingInfo, TestToken } from '../../../helpers/artifacts' import { checkPoint, - assertBigNumberEquality + assertBigNumberEquality, + assertBigNumbergt } from '../../../helpers/utils.js' import { expectEvent, expectRevert, BN } from '@openzeppelin/test-helpers' import { wallets, walletAmounts, freshDeploy, approveAndStake } from '../deployment' @@ -49,7 +50,7 @@ module.exports = function(accounts) { } describe('stake', function() { - function testStakeRevert(user, userPubkey, amount, stakeAmount, unspecified = false) { + function testStakeRevert(user, userPubkey, amount, stakeAmount, unspecified = false, commissionRate = 0) { before('Approve', async function() { this.initialBalance = await this.stakeManager.totalStakedFor(user) @@ -60,11 +61,11 @@ module.exports = function(accounts) { it('must revert', async function() { if (unspecified) { - await expectRevert.unspecified(this.stakeManager.stakeFor(user, stakeAmount, this.defaultHeimdallFee, false, userPubkey, { + await expectRevert.unspecified(this.stakeManager.stakeFor(user, stakeAmount, this.defaultHeimdallFee, commissionRate, false, userPubkey, { from: user })) } else { - await expectRevert(this.stakeManager.stakeFor(user, stakeAmount, this.defaultHeimdallFee, false, userPubkey, { + await expectRevert(this.stakeManager.stakeFor(user, stakeAmount, this.defaultHeimdallFee, commissionRate, false, userPubkey, { from: user }), 'Invalid signer') } @@ -87,7 +88,7 @@ module.exports = function(accounts) { }) it('must stake', async function() { - this.receipt = await this.stakeManager.stakeFor(user, stakeAmount, this.fee, false, userPubkey, { + this.receipt = await this.stakeManager.stakeFor(user, stakeAmount, this.fee, 0, false, userPubkey, { from: user }) }) @@ -114,6 +115,11 @@ module.exports = function(accounts) { assertBigNumberEquality(stakedFor, stakeAmount) }) + it('must have lastCommissionUpdate set', async function() { + const data = await this.stakeManager.validators(validatorId) + assertBigNumbergt(data.lastCommissionUpdate, 0) + }) + it('must have correct total staked balance', async function() { const stake = await this.stakeManager.currentValidatorSetTotalStake() assertBigNumberEquality(stake, stakeAmount) @@ -226,7 +232,7 @@ module.exports = function(accounts) { from: auctionUser }) const validatorId = await this.stakeManager.getValidatorId(wallets[2].getChecksumAddressString()) - await this.stakeManager.startAuction(validatorId, auctionBid, false, wallets[4].getPublicKeyString(), { + await this.stakeManager.startAuction(validatorId, auctionBid, 0, false, wallets[4].getPublicKeyString(), { from: auctionUser }) testRestake( @@ -240,6 +246,21 @@ module.exports = function(accounts) { }) }) + describe('when commission rate is greater than 100', function() { + before(prepareForTest(2, 1)) + + const amounts = walletAmounts[wallets[3].getAddressString()] + + testStakeRevert( + wallets[3].getChecksumAddressString(), + wallets[3].getPublicKeyString(), + amounts.amount, + amounts.stakeAmount, + true, + 101 + ) + }) + describe('stake beyond validator threshold', async function() { before(prepareForTest(2, 1)) diff --git a/test/units/staking/stakeManager/StakeManager.test.js b/test/units/staking/stakeManager/StakeManager.test.js index 963597e84..8fdf8cb70 100644 --- a/test/units/staking/stakeManager/StakeManager.test.js +++ b/test/units/staking/stakeManager/StakeManager.test.js @@ -11,6 +11,7 @@ import { buildTreeFee } from '../../../helpers/proofs.js' import { checkPoint, assertBigNumberEquality, + assertBigNumbergt, buildsubmitCheckpointPaylod, buildsubmitCheckpointPaylodWithVotes, encodeSigsForCheckpoint, @@ -21,6 +22,7 @@ import { generateFirstWallets, mnemonics } from '../../../helpers/wallets' import { wallets, freshDeploy, approveAndStake, walletAmounts } from '../deployment' import { buyVoucher } from '../ValidatorShareHelper.js' import { web3 } from '@openzeppelin/test-helpers/src/setup' +import { it } from 'ethers/wordlists' const { toWei } = web3.utils @@ -77,9 +79,9 @@ contract('StakeManager', async function(accounts) { return expectedBalance.mul(new BN(checkpointsPassed)) } - function testStartAuction(user, signerPubkey, bidAmount) { + function testStartAuction(user, signerPubkey, bidAmount, commissionRate = 0) { it('should bid', async function() { - this.receipt = await this.stakeManager.startAuction(this.validatorId, bidAmount, false, signerPubkey, { + this.receipt = await this.stakeManager.startAuction(this.validatorId, bidAmount, commissionRate, false, signerPubkey, { from: user }) }) @@ -102,6 +104,11 @@ contract('StakeManager', async function(accounts) { assert(auctionData.user === user) }) + it('validator auction must have correct commission rate', async function() { + let auctionData = await this.stakeManager.validatorAuction(this.validatorId) + assertBigNumberEquality(auctionData.commissionRate, commissionRate) + }) + it('balance must decrease by bid amount', async function() { assertBigNumberEquality( await this.stakeToken.balanceOf(user), @@ -173,6 +180,11 @@ contract('StakeManager', async function(accounts) { const currentBalance = await this.stakeToken.balanceOf(this.bidder) assertBigNumberEquality(this.bidderBalanceBeforeAuction.sub(new BN(this.bidAmount)).sub(new BN(this.heimdallFee)), currentBalance) }) + + it('new validator must have lastCommissionUpdate set', async function() { + const data = await this.stakeManager.validators(this.newValidatorId) + assertBigNumbergt(data.lastCommissionUpdate, 0) + }) } describe('updateCommissionRate', function() { @@ -1926,11 +1938,11 @@ contract('StakeManager', async function(accounts) { }) describe('when Alice bids', function() { - testStartAuction(Alice.getChecksumAddressString(), Alice.getPrivateKeyString(), aliceBidAmount) + testStartAuction(Alice.getChecksumAddressString(), Alice.getPrivateKeyString(), aliceBidAmount, 50) }) describe('when Bob bids', function() { - testStartAuction(Bob.getChecksumAddressString(), Bob.getPublicKeyString(), bobBidAmount) + testStartAuction(Bob.getChecksumAddressString(), Bob.getPublicKeyString(), bobBidAmount, 22) it('Alice must get her bid back', async function() { const currentBalance = await this.stakeToken.balanceOf(Alice.getAddressString()) @@ -1942,10 +1954,16 @@ contract('StakeManager', async function(accounts) { describe('reverts', function() { beforeEach('deploy', doDeploy) + it('when commission rate is greater than 100', async function() { + await expectRevert(this.stakeManager.startAuction(1, this.amount, 101, false, wallets[3].getPrivateKeyString(), { + from: wallets[3].getAddressString() + }), 'Incorrect value') + }) + it('when bid during non-auction period', async function() { let auctionPeriod = await this.stakeManager.auctionPeriod() await this.stakeManager.advanceEpoch((auctionPeriod).toNumber()) - await expectRevert(this.stakeManager.startAuction(1, this.amount, false, wallets[3].getPrivateKeyString(), { + await expectRevert(this.stakeManager.startAuction(1, this.amount, 0, false, wallets[3].getPrivateKeyString(), { from: wallets[3].getAddressString() }), 'Invalid auction period') }) @@ -1953,7 +1971,7 @@ contract('StakeManager', async function(accounts) { it('when trying to start and confirm in last epoch', async function() { this.validatorId = 1 await this.stakeManager.advanceEpoch(1) - await this.stakeManager.startAuction(this.validatorId, this.amount, false, wallets[3].getPublicKeyString(), { + await this.stakeManager.startAuction(this.validatorId, this.amount, 0, false, wallets[3].getPublicKeyString(), { from: wallets[3].getAddressString() }) await this.stakeToken.approve(this.stakeManager.address, web3.utils.toWei('1'), { @@ -1983,14 +2001,14 @@ contract('StakeManager', async function(accounts) { this.stakeManager.contract.methods.updateDynastyValue('7').encodeABI() ) - await expectRevert(this.stakeManager.startAuction(1, this.amount, false, wallets[3].getPrivateKeyString(), { + await expectRevert(this.stakeManager.startAuction(1, this.amount, 0, false, wallets[3].getPrivateKeyString(), { from: wallets[3].getAddressString() }), 'Cooldown period') }) it('when bid on unstaking validator', async function() { await this.stakeManager.unstake(1, { from: _initialStakers[0].getAddressString() }) - await expectRevert(this.stakeManager.startAuction(1, this.amount, false, wallets[3].getPrivateKeyString(), { + await expectRevert(this.stakeManager.startAuction(1, this.amount, 0, false, wallets[3].getPrivateKeyString(), { from: wallets[3].getAddressString() }), 'Invalid validator for an auction') }) @@ -2014,13 +2032,13 @@ contract('StakeManager', async function(accounts) { }) it('when validatorId is invalid', async function() { - await expectRevert.unspecified(this.stakeManager.startAuction(0, this.amount, false, wallets[3].getPrivateKeyString(), { + await expectRevert.unspecified(this.stakeManager.startAuction(0, this.amount, 0, false, wallets[3].getPrivateKeyString(), { from: wallets[3].getAddressString() })) }) it('when bid is too low', async function() { - await expectRevert(this.stakeManager.startAuction(1, web3.utils.toWei('100'), false, wallets[3].getPrivateKeyString(), { + await expectRevert(this.stakeManager.startAuction(1, web3.utils.toWei('100'), 0, false, wallets[3].getPrivateKeyString(), { from: wallets[3].getAddressString() }), 'Must bid higher') }) @@ -2059,7 +2077,7 @@ contract('StakeManager', async function(accounts) { this.bidderBalanceBeforeAuction = await this.stakeToken.balanceOf(this.bidder) this.totalStakedBeforeAuction = await this.stakeManager.totalStaked() - await this.stakeManager.startAuction(this.validatorId, bidAmount, false, this.bidderPubKey, { + await this.stakeManager.startAuction(this.validatorId, bidAmount, 0, false, this.bidderPubKey, { from: this.bidder }) @@ -2315,7 +2333,7 @@ contract('StakeManager', async function(accounts) { }) it('bid must revert', async function() { - await expectRevert(this.stakeManager.startAuction(this.validatorId, bidAmount, false, bidderPubKey, { + await expectRevert(this.stakeManager.startAuction(this.validatorId, bidAmount, 0, false, bidderPubKey, { from: bidder }), 'Cooldown period') }) @@ -2329,7 +2347,7 @@ contract('StakeManager', async function(accounts) { it('must bid', async function() { await this.stakeToken.mint(bidder, bidAmount) await this.stakeToken.approve(this.stakeManager.address, bidAmount, { from: bidder }) - await this.stakeManager.startAuction(this.validatorId, bidAmount, false, bidderPubKey, { + await this.stakeManager.startAuction(this.validatorId, bidAmount, 0, false, bidderPubKey, { from: bidder }) }) From 4386df40400950e6354b85cbbb2bd523eaa5d7f0 Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Wed, 24 Mar 2021 11:48:51 +0700 Subject: [PATCH 07/11] fix: test --- test/units/staking/stakeManager/StakeManager.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/units/staking/stakeManager/StakeManager.test.js b/test/units/staking/stakeManager/StakeManager.test.js index 8fdf8cb70..1261f3f4e 100644 --- a/test/units/staking/stakeManager/StakeManager.test.js +++ b/test/units/staking/stakeManager/StakeManager.test.js @@ -22,7 +22,6 @@ import { generateFirstWallets, mnemonics } from '../../../helpers/wallets' import { wallets, freshDeploy, approveAndStake, walletAmounts } from '../deployment' import { buyVoucher } from '../ValidatorShareHelper.js' import { web3 } from '@openzeppelin/test-helpers/src/setup' -import { it } from 'ethers/wordlists' const { toWei } = web3.utils From fc1c16e0789f3f910f985c71608888861cbcedab Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Wed, 24 Mar 2021 11:48:51 +0700 Subject: [PATCH 08/11] Revert "fix: test" This reverts commit 4386df40400950e6354b85cbbb2bd523eaa5d7f0. --- test/units/staking/stakeManager/StakeManager.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/units/staking/stakeManager/StakeManager.test.js b/test/units/staking/stakeManager/StakeManager.test.js index 1261f3f4e..8fdf8cb70 100644 --- a/test/units/staking/stakeManager/StakeManager.test.js +++ b/test/units/staking/stakeManager/StakeManager.test.js @@ -22,6 +22,7 @@ import { generateFirstWallets, mnemonics } from '../../../helpers/wallets' import { wallets, freshDeploy, approveAndStake, walletAmounts } from '../deployment' import { buyVoucher } from '../ValidatorShareHelper.js' import { web3 } from '@openzeppelin/test-helpers/src/setup' +import { it } from 'ethers/wordlists' const { toWei } = web3.utils From 739b55cc3401d0c3ea1b0fa6877bb080d608446e Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Tue, 23 Mar 2021 20:45:48 +0700 Subject: [PATCH 09/11] Revert "chg: pass commission rate into auction and stakeFor to avoid extra tx" This reverts commit 37bc88e6deff36d450a426c78942fd19c5f9f762. --- .../staking/stakeManager/IStakeManager.sol | 3 -- .../staking/stakeManager/StakeManager.sol | 23 ++++------ .../stakeManager/StakeManagerExtension.sol | 5 --- .../stakeManager/StakeManagerStorage.sol | 1 - .../staking/validatorShare/ValidatorShare.sol | 2 +- test/units/staking/deployment.js | 4 +- .../stakeManager/StakeManager.Staking.js | 35 +++------------ .../staking/stakeManager/StakeManager.test.js | 44 ++++++------------- 8 files changed, 31 insertions(+), 86 deletions(-) diff --git a/contracts/staking/stakeManager/IStakeManager.sol b/contracts/staking/stakeManager/IStakeManager.sol index 9dae193a0..867030fca 100644 --- a/contracts/staking/stakeManager/IStakeManager.sol +++ b/contracts/staking/stakeManager/IStakeManager.sol @@ -5,7 +5,6 @@ contract IStakeManager { function startAuction( uint256 validatorId, uint256 amount, - uint256 commissionRate, bool acceptDelegation, bytes calldata signerPubkey ) external; @@ -32,7 +31,6 @@ contract IStakeManager { address user, uint256 amount, uint256 heimdallFee, - uint256 commissionRate, bool acceptDelegation, bytes memory signerPubkey ) public; @@ -72,7 +70,6 @@ contract IStakeManager { uint256 heimdallFee, uint256 validatorId, uint256 auctionAmount, - uint256 commissionRate, bool acceptDelegation, bytes calldata signerPubkey ) external; diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 086edff54..22deda6d8 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -352,9 +352,8 @@ contract StakeManager is function startAuction( uint256 validatorId, uint256 amount, - uint256 commissionRate, - bool acceptDelegation, - bytes calldata signerPubkey + bool _acceptDelegation, + bytes calldata _signerPubkey ) external onlyWhenUnlocked { delegatedFwd( extensionCode, @@ -362,9 +361,8 @@ contract StakeManager is StakeManagerExtension(extensionCode).startAuction.selector, validatorId, amount, - commissionRate, - acceptDelegation, - signerPubkey + _acceptDelegation, + _signerPubkey ) ); } @@ -389,7 +387,6 @@ contract StakeManager is uint256 heimdallFee, uint256 validatorId, uint256 auctionAmount, - uint256 commissionRate, bool acceptDelegation, bytes calldata signerPubkey ) external { @@ -398,7 +395,7 @@ contract StakeManager is _transferAndTopUp(auctionUser, auctionUser, heimdallFee, 0); _unstake(validatorId, currentEpoch); - uint256 newValidatorId = _stakeFor(auctionUser, auctionAmount, commissionRate, acceptDelegation, signerPubkey); + uint256 newValidatorId = _stakeFor(auctionUser, auctionAmount, acceptDelegation, signerPubkey); logger.logConfirmAuction(newValidatorId, validatorId, auctionAmount); } @@ -441,14 +438,13 @@ contract StakeManager is address user, uint256 amount, uint256 heimdallFee, - uint256 commissionRate, bool acceptDelegation, bytes memory signerPubkey ) public onlyWhenUnlocked { require(currentValidatorSetSize() < validatorThreshold, "no more slots"); require(amount >= minDeposit, "not enough deposit"); _transferAndTopUp(user, msg.sender, heimdallFee, amount); - _stakeFor(user, amount, commissionRate, acceptDelegation, signerPubkey); + _stakeFor(user, amount, acceptDelegation, signerPubkey); } function unstakeClaim(uint256 validatorId) public onlyStaker(validatorId) { @@ -1050,12 +1046,9 @@ contract StakeManager is function _stakeFor( address user, uint256 amount, - uint256 commissionRate, bool acceptDelegation, bytes memory signerPubkey ) internal returns (uint256) { - require(commissionRate <= MAX_COMMISION_RATE, "Incorrect value"); - address signer = _getAndAssertSigner(signerPubkey); uint256 _currentEpoch = currentEpoch; uint256 validatorId = NFTCounter; @@ -1075,8 +1068,8 @@ contract StakeManager is ? validatorShareFactory.create(validatorId, address(_logger), registry) : address(0x0), status: Status.Active, - commissionRate: commissionRate, - lastCommissionUpdate: _currentEpoch, // commission rate was set explicitly + commissionRate: 0, + lastCommissionUpdate: 0, delegatorsReward: INITIALIZED_AMOUNT, delegatedAmount: 0, initialRewardPerStake: rewardPerStake diff --git a/contracts/staking/stakeManager/StakeManagerExtension.sol b/contracts/staking/stakeManager/StakeManagerExtension.sol index bab10d420..c74dbcca4 100644 --- a/contracts/staking/stakeManager/StakeManagerExtension.sol +++ b/contracts/staking/stakeManager/StakeManagerExtension.sol @@ -20,14 +20,11 @@ contract StakeManagerExtension is StakeManagerStorage, Initializable, StakeManag function startAuction( uint256 validatorId, uint256 amount, - uint256 commissionRate, bool _acceptDelegation, bytes calldata _signerPubkey ) external { uint256 currentValidatorAmount = validators[validatorId].amount; - require(commissionRate <= MAX_COMMISION_RATE, "Incorrect value"); - require( validators[validatorId].deactivationEpoch == 0 && currentValidatorAmount != 0, "Invalid validator for an auction" @@ -75,7 +72,6 @@ contract StakeManagerExtension is StakeManagerStorage, Initializable, StakeManag // create new auction auction.amount = amount; auction.user = msg.sender; - auction.commissionRate = commissionRate; auction.acceptDelegation = _acceptDelegation; auction.signerPubkey = _signerPubkey; @@ -120,7 +116,6 @@ contract StakeManagerExtension is StakeManagerStorage, Initializable, StakeManag heimdallFee, validatorId, auctionAmount, - auction.commissionRate, auction.acceptDelegation, auction.signerPubkey ); diff --git a/contracts/staking/stakeManager/StakeManagerStorage.sol b/contracts/staking/stakeManager/StakeManagerStorage.sol index d30bd3fd3..6b448a838 100644 --- a/contracts/staking/stakeManager/StakeManagerStorage.sol +++ b/contracts/staking/stakeManager/StakeManagerStorage.sol @@ -15,7 +15,6 @@ contract StakeManagerStorage is GovernanceLockable, RootChainable { struct Auction { uint256 amount; uint256 startEpoch; - uint256 commissionRate; address user; bool acceptDelegation; bytes signerPubkey; diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index eda5ec4f9..f9c10e460 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -86,7 +86,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I function withdrawExchangeRate() public view returns (uint256) { uint256 precision = _getRatePrecision(); - if (validatorId < 9) { + if (validatorId < 8) { // fix of potentially broken withdrawals for future unbonding // foundation validators have no slashing enabled and thus we can return default exchange rate // because without slashing rate will stay constant diff --git a/test/units/staking/deployment.js b/test/units/staking/deployment.js index 02481b5d2..f6a1ca53f 100644 --- a/test/units/staking/deployment.js +++ b/test/units/staking/deployment.js @@ -60,7 +60,7 @@ export async function freshDeploy() { this.defaultHeimdallFee = new BN(web3.utils.toWei('1')) } -export async function approveAndStake({ wallet, stakeAmount, approveAmount, acceptDelegation = false, heimdallFee, noMinting = false, signer, commissionRate = 0 }) { +export async function approveAndStake({ wallet, stakeAmount, approveAmount, acceptDelegation = false, heimdallFee, noMinting = false, signer }) { const fee = heimdallFee || this.defaultHeimdallFee const mintAmount = new BN(approveAmount || stakeAmount).add(new BN(fee)) @@ -80,7 +80,7 @@ export async function approveAndStake({ wallet, stakeAmount, approveAmount, acce from: wallet.getAddressString() }) - await this.stakeManager.stakeFor(wallet.getAddressString(), stakeAmount, fee, commissionRate, acceptDelegation, signer || wallet.getPublicKeyString(), { + await this.stakeManager.stakeFor(wallet.getAddressString(), stakeAmount, fee, acceptDelegation, signer || wallet.getPublicKeyString(), { from: wallet.getAddressString() }) } diff --git a/test/units/staking/stakeManager/StakeManager.Staking.js b/test/units/staking/stakeManager/StakeManager.Staking.js index 1ac7898d7..a753b86b0 100644 --- a/test/units/staking/stakeManager/StakeManager.Staking.js +++ b/test/units/staking/stakeManager/StakeManager.Staking.js @@ -1,9 +1,8 @@ -import { StakingInfo, TestToken } from '../../../helpers/artifacts' +import { StakingInfo, TestToken, ValidatorShare } from '../../../helpers/artifacts' import { checkPoint, - assertBigNumberEquality, - assertBigNumbergt + assertBigNumberEquality } from '../../../helpers/utils.js' import { expectEvent, expectRevert, BN } from '@openzeppelin/test-helpers' import { wallets, walletAmounts, freshDeploy, approveAndStake } from '../deployment' @@ -50,7 +49,7 @@ module.exports = function(accounts) { } describe('stake', function() { - function testStakeRevert(user, userPubkey, amount, stakeAmount, unspecified = false, commissionRate = 0) { + function testStakeRevert(user, userPubkey, amount, stakeAmount, unspecified = false) { before('Approve', async function() { this.initialBalance = await this.stakeManager.totalStakedFor(user) @@ -61,11 +60,11 @@ module.exports = function(accounts) { it('must revert', async function() { if (unspecified) { - await expectRevert.unspecified(this.stakeManager.stakeFor(user, stakeAmount, this.defaultHeimdallFee, commissionRate, false, userPubkey, { + await expectRevert.unspecified(this.stakeManager.stakeFor(user, stakeAmount, this.defaultHeimdallFee, false, userPubkey, { from: user })) } else { - await expectRevert(this.stakeManager.stakeFor(user, stakeAmount, this.defaultHeimdallFee, commissionRate, false, userPubkey, { + await expectRevert(this.stakeManager.stakeFor(user, stakeAmount, this.defaultHeimdallFee, false, userPubkey, { from: user }), 'Invalid signer') } @@ -88,7 +87,7 @@ module.exports = function(accounts) { }) it('must stake', async function() { - this.receipt = await this.stakeManager.stakeFor(user, stakeAmount, this.fee, 0, false, userPubkey, { + this.receipt = await this.stakeManager.stakeFor(user, stakeAmount, this.fee, false, userPubkey, { from: user }) }) @@ -115,11 +114,6 @@ module.exports = function(accounts) { assertBigNumberEquality(stakedFor, stakeAmount) }) - it('must have lastCommissionUpdate set', async function() { - const data = await this.stakeManager.validators(validatorId) - assertBigNumbergt(data.lastCommissionUpdate, 0) - }) - it('must have correct total staked balance', async function() { const stake = await this.stakeManager.currentValidatorSetTotalStake() assertBigNumberEquality(stake, stakeAmount) @@ -232,7 +226,7 @@ module.exports = function(accounts) { from: auctionUser }) const validatorId = await this.stakeManager.getValidatorId(wallets[2].getChecksumAddressString()) - await this.stakeManager.startAuction(validatorId, auctionBid, 0, false, wallets[4].getPublicKeyString(), { + await this.stakeManager.startAuction(validatorId, auctionBid, false, wallets[4].getPublicKeyString(), { from: auctionUser }) testRestake( @@ -246,21 +240,6 @@ module.exports = function(accounts) { }) }) - describe('when commission rate is greater than 100', function() { - before(prepareForTest(2, 1)) - - const amounts = walletAmounts[wallets[3].getAddressString()] - - testStakeRevert( - wallets[3].getChecksumAddressString(), - wallets[3].getPublicKeyString(), - amounts.amount, - amounts.stakeAmount, - true, - 101 - ) - }) - describe('stake beyond validator threshold', async function() { before(prepareForTest(2, 1)) diff --git a/test/units/staking/stakeManager/StakeManager.test.js b/test/units/staking/stakeManager/StakeManager.test.js index 8fdf8cb70..963597e84 100644 --- a/test/units/staking/stakeManager/StakeManager.test.js +++ b/test/units/staking/stakeManager/StakeManager.test.js @@ -11,7 +11,6 @@ import { buildTreeFee } from '../../../helpers/proofs.js' import { checkPoint, assertBigNumberEquality, - assertBigNumbergt, buildsubmitCheckpointPaylod, buildsubmitCheckpointPaylodWithVotes, encodeSigsForCheckpoint, @@ -22,7 +21,6 @@ import { generateFirstWallets, mnemonics } from '../../../helpers/wallets' import { wallets, freshDeploy, approveAndStake, walletAmounts } from '../deployment' import { buyVoucher } from '../ValidatorShareHelper.js' import { web3 } from '@openzeppelin/test-helpers/src/setup' -import { it } from 'ethers/wordlists' const { toWei } = web3.utils @@ -79,9 +77,9 @@ contract('StakeManager', async function(accounts) { return expectedBalance.mul(new BN(checkpointsPassed)) } - function testStartAuction(user, signerPubkey, bidAmount, commissionRate = 0) { + function testStartAuction(user, signerPubkey, bidAmount) { it('should bid', async function() { - this.receipt = await this.stakeManager.startAuction(this.validatorId, bidAmount, commissionRate, false, signerPubkey, { + this.receipt = await this.stakeManager.startAuction(this.validatorId, bidAmount, false, signerPubkey, { from: user }) }) @@ -104,11 +102,6 @@ contract('StakeManager', async function(accounts) { assert(auctionData.user === user) }) - it('validator auction must have correct commission rate', async function() { - let auctionData = await this.stakeManager.validatorAuction(this.validatorId) - assertBigNumberEquality(auctionData.commissionRate, commissionRate) - }) - it('balance must decrease by bid amount', async function() { assertBigNumberEquality( await this.stakeToken.balanceOf(user), @@ -180,11 +173,6 @@ contract('StakeManager', async function(accounts) { const currentBalance = await this.stakeToken.balanceOf(this.bidder) assertBigNumberEquality(this.bidderBalanceBeforeAuction.sub(new BN(this.bidAmount)).sub(new BN(this.heimdallFee)), currentBalance) }) - - it('new validator must have lastCommissionUpdate set', async function() { - const data = await this.stakeManager.validators(this.newValidatorId) - assertBigNumbergt(data.lastCommissionUpdate, 0) - }) } describe('updateCommissionRate', function() { @@ -1938,11 +1926,11 @@ contract('StakeManager', async function(accounts) { }) describe('when Alice bids', function() { - testStartAuction(Alice.getChecksumAddressString(), Alice.getPrivateKeyString(), aliceBidAmount, 50) + testStartAuction(Alice.getChecksumAddressString(), Alice.getPrivateKeyString(), aliceBidAmount) }) describe('when Bob bids', function() { - testStartAuction(Bob.getChecksumAddressString(), Bob.getPublicKeyString(), bobBidAmount, 22) + testStartAuction(Bob.getChecksumAddressString(), Bob.getPublicKeyString(), bobBidAmount) it('Alice must get her bid back', async function() { const currentBalance = await this.stakeToken.balanceOf(Alice.getAddressString()) @@ -1954,16 +1942,10 @@ contract('StakeManager', async function(accounts) { describe('reverts', function() { beforeEach('deploy', doDeploy) - it('when commission rate is greater than 100', async function() { - await expectRevert(this.stakeManager.startAuction(1, this.amount, 101, false, wallets[3].getPrivateKeyString(), { - from: wallets[3].getAddressString() - }), 'Incorrect value') - }) - it('when bid during non-auction period', async function() { let auctionPeriod = await this.stakeManager.auctionPeriod() await this.stakeManager.advanceEpoch((auctionPeriod).toNumber()) - await expectRevert(this.stakeManager.startAuction(1, this.amount, 0, false, wallets[3].getPrivateKeyString(), { + await expectRevert(this.stakeManager.startAuction(1, this.amount, false, wallets[3].getPrivateKeyString(), { from: wallets[3].getAddressString() }), 'Invalid auction period') }) @@ -1971,7 +1953,7 @@ contract('StakeManager', async function(accounts) { it('when trying to start and confirm in last epoch', async function() { this.validatorId = 1 await this.stakeManager.advanceEpoch(1) - await this.stakeManager.startAuction(this.validatorId, this.amount, 0, false, wallets[3].getPublicKeyString(), { + await this.stakeManager.startAuction(this.validatorId, this.amount, false, wallets[3].getPublicKeyString(), { from: wallets[3].getAddressString() }) await this.stakeToken.approve(this.stakeManager.address, web3.utils.toWei('1'), { @@ -2001,14 +1983,14 @@ contract('StakeManager', async function(accounts) { this.stakeManager.contract.methods.updateDynastyValue('7').encodeABI() ) - await expectRevert(this.stakeManager.startAuction(1, this.amount, 0, false, wallets[3].getPrivateKeyString(), { + await expectRevert(this.stakeManager.startAuction(1, this.amount, false, wallets[3].getPrivateKeyString(), { from: wallets[3].getAddressString() }), 'Cooldown period') }) it('when bid on unstaking validator', async function() { await this.stakeManager.unstake(1, { from: _initialStakers[0].getAddressString() }) - await expectRevert(this.stakeManager.startAuction(1, this.amount, 0, false, wallets[3].getPrivateKeyString(), { + await expectRevert(this.stakeManager.startAuction(1, this.amount, false, wallets[3].getPrivateKeyString(), { from: wallets[3].getAddressString() }), 'Invalid validator for an auction') }) @@ -2032,13 +2014,13 @@ contract('StakeManager', async function(accounts) { }) it('when validatorId is invalid', async function() { - await expectRevert.unspecified(this.stakeManager.startAuction(0, this.amount, 0, false, wallets[3].getPrivateKeyString(), { + await expectRevert.unspecified(this.stakeManager.startAuction(0, this.amount, false, wallets[3].getPrivateKeyString(), { from: wallets[3].getAddressString() })) }) it('when bid is too low', async function() { - await expectRevert(this.stakeManager.startAuction(1, web3.utils.toWei('100'), 0, false, wallets[3].getPrivateKeyString(), { + await expectRevert(this.stakeManager.startAuction(1, web3.utils.toWei('100'), false, wallets[3].getPrivateKeyString(), { from: wallets[3].getAddressString() }), 'Must bid higher') }) @@ -2077,7 +2059,7 @@ contract('StakeManager', async function(accounts) { this.bidderBalanceBeforeAuction = await this.stakeToken.balanceOf(this.bidder) this.totalStakedBeforeAuction = await this.stakeManager.totalStaked() - await this.stakeManager.startAuction(this.validatorId, bidAmount, 0, false, this.bidderPubKey, { + await this.stakeManager.startAuction(this.validatorId, bidAmount, false, this.bidderPubKey, { from: this.bidder }) @@ -2333,7 +2315,7 @@ contract('StakeManager', async function(accounts) { }) it('bid must revert', async function() { - await expectRevert(this.stakeManager.startAuction(this.validatorId, bidAmount, 0, false, bidderPubKey, { + await expectRevert(this.stakeManager.startAuction(this.validatorId, bidAmount, false, bidderPubKey, { from: bidder }), 'Cooldown period') }) @@ -2347,7 +2329,7 @@ contract('StakeManager', async function(accounts) { it('must bid', async function() { await this.stakeToken.mint(bidder, bidAmount) await this.stakeToken.approve(this.stakeManager.address, bidAmount, { from: bidder }) - await this.stakeManager.startAuction(this.validatorId, bidAmount, 0, false, bidderPubKey, { + await this.stakeManager.startAuction(this.validatorId, bidAmount, false, bidderPubKey, { from: bidder }) }) From b7a7c91c1ebcbd9e49297c9533fd552adacbc725 Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Wed, 24 Mar 2021 13:28:37 +0700 Subject: [PATCH 10/11] fix: test --- test/units/staking/ValidatorShare.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/units/staking/ValidatorShare.test.js b/test/units/staking/ValidatorShare.test.js index dacf27e62..0e2be563a 100644 --- a/test/units/staking/ValidatorShare.test.js +++ b/test/units/staking/ValidatorShare.test.js @@ -1786,7 +1786,7 @@ contract('ValidatorShare', async function() { }) it('must emit DelegatorUnstakeWithId', async function() { - await expectEvent.inTransaction(this.receipt.tx, StakingInfo, 'DelegatorUnstakeWithId', { + await expectEvent.inTransaction(this.receipt.tx, EventsHub, 'DelegatorUnstakeWithId', { validatorId: this.validatorId, user: this.user, amount: this.claimAmount, @@ -1801,7 +1801,7 @@ contract('ValidatorShare', async function() { }) it('must emit DelegatorUnstakeWithId', async function() { - await expectEvent.inTransaction(this.receipt.tx, StakingInfo, 'DelegatorUnstakeWithId', { + await expectEvent.inTransaction(this.receipt.tx, EventsHub, 'DelegatorUnstakeWithId', { validatorId: this.validatorId, user: this.user, amount: this.claimAmount, From f561c214ba3f3d454e9667874f1be45f9ad81a2a Mon Sep 17 00:00:00 2001 From: Denis Ermolin Date: Sat, 27 Mar 2021 00:07:40 +0700 Subject: [PATCH 11/11] fix: override isOwner --- contracts/staking/stakeManager/StakeManager.sol | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 22deda6d8..f11909521 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -107,6 +107,15 @@ contract StakeManager is delegationEnabled = true; } + function isOwner() public view returns (bool) { + address _owner; + bytes32 position = keccak256("matic.network.proxy.owner"); + assembly { + _owner := sload(position) + } + return msg.sender == _owner; + } + /** Public View Methods */