sherlock-audit / 2024-06-leveraged-vaults-judging

11 stars 8 forks source link

DenTonylifer - VaultRewarderLib cannot receive rewards for boosted staking #58

Closed sherlock-admin3 closed 4 months ago

sherlock-admin3 commented 4 months ago

DenTonylifer

High

VaultRewarderLib cannot receive rewards for boosted staking

Summary

VaultRewarderLib.sol cannot receive rewards for booster staking, therefore users will not be able to receive rewards.

Vulnerability Detail

For additional profit, the protocol restakes user deposits to booster contracts, such as CONVEX/AURA. These contracts accumulate rewards, which the protocol then claims and distributes to users. Stackers here are such vaults as BalancerComposableAuraVault.sol, Curve2TokenConvexVault.sol and BalancerWeightedAuraVault.sol:

// leveraged-vaults-private/contracts/vaults/curve/Curve2TokenConvexVault.sol

 if (Deployments.CHAIN_ID == Constants.CHAIN_ID_MAINNET) {
            success = IConvexBooster(CONVEX_BOOSTER).deposit(CONVEX_POOL_ID, lpTokens, true);
        } else if (Deployments.CHAIN_ID == Constants.CHAIN_ID_ARBITRUM) {
            success = IConvexBoosterArbitrum(CONVEX_BOOSTER).deposit(CONVEX_POOL_ID, lpTokens);
        }

Then VaultRewarderLib.sol claims earned rewards:

if (r.poolType == RewardPoolType.AURA) {
            require(IAuraRewardPool(r.rewardPool).getReward(address(this), true));
        } else if (r.poolType == RewardPoolType.CONVEX_MAINNET) {
            require(IConvexRewardPool(r.rewardPool).getReward(address(this), true));
        } else if (r.poolType == RewardPoolType.CONVEX_ARBITRUM) {
            IConvexRewardPoolArbitrum(r.rewardPool).getReward(address(this));

The problem is that the contact calls the function getReward() with the address(this) as a parameter, while the rewards are accumulated to the addresses of the stakers (ie, the above-mentioned vaults):

// Booster.sol function deposit(uint256 _pid, uint256 _amount, bool _stake) public returns(bool){ //... if(_stake) IRewards(rewardContract).stakeFor(msg.sender,_amount); //... }

//BaseRewardPool.sol function stakeFor(address _for, uint256 _amount) public updateReward(_for) returns(bool) { //... //also stake to linked rewards for(uint i=0; i < extraRewards.length; i++){ IRewards(extraRewards[i]).stake(_for, _amount); }

    //give to _for
    _totalSupply = _totalSupply.add(_amount);
    _balances[_for] = _balances[_for].add(_amount);
    //...
}
- rewards will be sent to the addresses of the stakers:
```solidity
//BaseRewardPool.sol
function getReward(address _account, bool _claimExtras) public updateReward(_account) returns(bool){
        uint256 reward = earned(_account);
        if (reward > 0) {
            rewards[_account] = 0;
            rewardToken.safeTransfer(_account, reward);
            IDeposit(operator).rewardClaimed(pid, _account, reward);
            emit RewardPaid(_account, reward);
        }
        //...
    }

The VaultRewarderLib.sol contract does not make any stakes to CONVEX/AURA, nor do other contracts make stakes on its behalf, thus it cannot accumulate any rewards.

Impact

VaultRewarderLib.sol cannot receive rewards for boosted staking, therefore users will not be able to receive rewards.

Code Snippet

Link

Tool used

Manual Review

Recommendation

Since using a before/after balance check when claiming rewards is problematic (even with the correct parameters in getReward()), it's better to allow vaults to receive rewards and forward them to the VaultRewarderLib.sol so they can then be distributed to users.

sherlock-admin2 commented 4 months ago

1 comment(s) were left on this issue during the judging contest.

0xmystery commented:

Lacks proof to substantiate the bug