Lucene search

K
code423n4Code4renaCODE423N4:2022-04-MIMO-FINDINGS-ISSUES-103
HistoryMay 02, 2022 - 12:00 a.m.

In GenericMinerV2 get more reward by staking in votingEscrow and calling syncStake()

2022-05-0200:00:00
Code4rena
github.com
3
genericminerv2
votingescrow
syncstake
security
vulnerability
refresh
releaserewards

Lines of code
<https://github.com/code-423n4/2022-04-mimo/blob/b18670f44d595483df2c0f76d1c57a7bfbfbc083/core/contracts/liquidityMining/v2/VotingMinerV2.sol#L67-L71&gt;

Vulnerability details

Impact

User can withdraw & deposit in votingEscrow contract and then call syncStake() function of VotingMinerV2 to update his stake and stakeWithBoost with his new balance, and then he can call releaseRewards() to get more reward than he spoused to.

Proof of Concept

This is syncStake() code:

  function syncStake(address _user) public override {
    UserInfo memory _userInfo = _users[_user];
    _syncStake(_user, _userInfo);
    _updateBoost(_user, _userInfo);
  }

which calls _syncStake() with userInfo and in _syncStake(), user’s stake amount get updated to _a.votingEscrow().balanceOf(_user).

  function _syncStake(address _user, UserInfo memory _userInfo) internal {
    uint256 votingPower = _a.votingEscrow().balanceOf(_user);
    _totalStake = _totalStake.add(votingPower).sub(_userInfo.stake);
    _userInfo.stake = votingPower;
  }

then _updateBoost() has been called, which the code is:

  function _updateBoost(address _user, UserInfo memory _userInfo) internal {
    // if user had a boost already, first remove it from the totalStakeWithBoost
    if (_userInfo.stakeWithBoost &gt; 0) {
      _totalStakeWithBoost = _totalStakeWithBoost.sub(_userInfo.stakeWithBoost);
    }
    uint256 multiplier = _getBoostMultiplier(_user);
    _userInfo.stakeWithBoost = _userInfo.stake.wadMul(multiplier);
    _totalStakeWithBoost = _totalStakeWithBoost.add(_userInfo.stakeWithBoost);
    _users[_user] = _userInfo;
  }

it’s updating _userInfo.stakeWithBoost based on _userInfo.stake which is the latest value of user balance, but refresh() or releaseRewards() don’t called so user will have pending rewards but his stake amount is updated.
So without calling releaseRewards(user), his stake and stakeWithBoost amount get updated. which will make contract to give user more share of rewards and user don’t need to keep his assets staked.

Tools Used

VIM

Recommended Mitigation Steps

call refresh() or releaseRewards() before updating user stake or stakeWithBoost amount


The text was updated successfully, but these errors were encountered:

All reactions