diff --git a/contracts/staking/EventsHub.sol b/contracts/staking/EventsHub.sol index f49fc9db7..b38f2fabd 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 logDelegatorUnstakedWithId( + uint256 validatorId, + address user, + uint256 amount, + uint256 nonce + ) public onlyValidatorContract(validatorId) { + emit DelegatorUnstakeWithId(validatorId, user, amount, nonce); } event RewardParams( 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 */ diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index a4e37ad08..f9c10e460 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; @@ -186,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( @@ -251,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().logDelegatorUnstakedWithId(validatorId, msg.sender, amount, unbondNonce); } /** @@ -291,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, @@ -303,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) { @@ -321,7 +325,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 +344,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) { diff --git a/test/units/staking/ValidatorShare.test.js b/test/units/staking/ValidatorShare.test.js index aea3c512f..0e2be563a 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() { - await expectEvent.inTransaction(this.receipt.tx, StakingInfo, 'DelegatorUnstaked', { + it('must emit DelegatorUnstakeWithId', async function() { + await expectEvent.inTransaction(this.receipt.tx, EventsHub, 'DelegatorUnstakeWithId', { 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() { - await expectEvent.inTransaction(this.receipt.tx, StakingInfo, 'DelegatorUnstaked', { + it('must emit DelegatorUnstakeWithId', async function() { + await expectEvent.inTransaction(this.receipt.tx, EventsHub, 'DelegatorUnstakeWithId', { validatorId: this.validatorId, user: this.user, - amount: this.claimAmount + amount: this.claimAmount, + nonce: '2' }) })