Lucene search

K
code423n4Code4renaCODE423N4:2023-07-RESERVE-FINDINGS-ISSUES-11
HistoryAug 03, 2023 - 12:00 a.m.

ConvexStakingWrapper.sol after shutdown,rewards can be steal

2023-08-0300:00:00
Code4rena
github.com
5
vulnerability
theft
shutdown
tokens
rewards
mitigation
code
update
checkpoint
claim
security

7 High

AI Score

Confidence

Low

Lines of code

Vulnerability details

Impact

After shutdown, checkpoints are stopped, leading to possible theft of rewards.

Proof of Concept

ConvexStakingWrapper No more checkpoints after shutdown, i.e. no updates reward.reward_integral_for[user]

    function _beforeTokenTransfer(
        address _from,
        address _to,
        uint256
    ) internal override {
@>      _checkpoint([_from, _to]);
    }

    function _checkpoint(address[2] memory _accounts) internal nonReentrant {
        //if shutdown, no longer checkpoint in case there are problems
@>      if (isShutdown()) return;

        uint256 supply = _getTotalSupply();
        uint256[2] memory depositedBalance;
        depositedBalance[0] = _getDepositedBalance(_accounts[0]);
        depositedBalance[1] = _getDepositedBalance(_accounts[1]);

        IRewardStaking(convexPool).getReward(address(this), true);

        _claimExtras();

        uint256 rewardCount = rewards.length;
        for (uint256 i = 0; i < rewardCount; i++) {
            _calcRewardIntegral(i, _accounts, depositedBalance, supply, false);
        }
    }    

This would result in, after shutdown, being able to steal rewards by transferring tokens to new users

Example:
Suppose the current
reward.reward_integral = 1000

When a shutdown occurs

  1. alice transfers 100 to the new user, bob.
    Since bob is the new user and _beforeTokenTransfer()->_checkpoint() is not actually executed
    Result.
    balanceOf[bob] = 100
    reward.reward_integral_for[bob] = 0

  2. bob executes claimRewards() to steal the reward
    reward amount = balanceOf[bob] * (reward.reward_integral - reward.reward_integral_for[bob])
    = 100 * (1000-0)

  3. bob transfers the balance to other new users, looping steps 1-2 and stealing all rewards

Tools Used

Recommended Mitigation Steps

Still execute _checkpoint

    function _checkpoint(address[2] memory _accounts) internal nonReentrant {
        //if shutdown, no longer checkpoint in case there are problems
 -      if (isShutdown()) return;

        uint256 supply = _getTotalSupply();
        uint256[2] memory depositedBalance;
        depositedBalance[0] = _getDepositedBalance(_accounts[0]);
        depositedBalance[1] = _getDepositedBalance(_accounts[1]);

        IRewardStaking(convexPool).getReward(address(this), true);

        _claimExtras();

        uint256 rewardCount = rewards.length;
        for (uint256 i = 0; i < rewardCount; i++) {
            _calcRewardIntegral(i, _accounts, depositedBalance, supply, false);
        }
    }    

Assessed type

Context


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

All reactions

7 High

AI Score

Confidence

Low