sherlock-audit / 2024-06-boost-aa-wallet-judging

3 stars 1 forks source link

0xloophole - Incorrect Reward Decay Calculation in CGDAIncentive #446

Open sherlock-admin2 opened 1 month ago

sherlock-admin2 commented 1 month ago

0xloophole

Medium

Incorrect Reward Decay Calculation in CGDAIncentive

Details

The claim function in CGDAIncentive aims to reduce the currentReward by a fixed rewardDecay after each claim. However, the current implementation contains a logical error in how rewardDecay is applied when the remaining reward is less than the rewardDecay.

Code Snippet

https://github.com/sherlock-audit/2024-06-boost-aa-wallet/blob/main/boost-protocol/packages/evm/contracts/incentives/CGDAIncentive.sol#L85

function claim(address claimTarget, bytes calldata) external virtual override onlyOwner returns (bool) {
  // ... other logic ...

  // Calculate the current reward and update the state
  uint256 reward = currentReward();
  cgdaParams.lastClaimTime = block.timestamp;
  cgdaParams.currentReward =
    reward > cgdaParams.rewardDecay ? reward - cgdaParams.rewardDecay : cgdaParams.rewardDecay; // Issue here

  // ... transfer logic ...
}

The code intends to subtract rewardDecay from the reward after each claim, unless the remaining reward is less than rewardDecay. In that case, it aims to set the currentReward to the remaining amount. However, the code mistakenly sets the currentReward to cgdaParams.rewardDecay itself, rather than the remaining balance (reward), which is incorrect.

This error can lead to:

Reward Reset: Instead of the reward gradually decreasing to zero, it could potentially reset to the rewardDecay value after reaching a point where the reward is less than rewardDecay. Inaccurate Incentive Dynamics: The intended continuous gradual decrease in reward would not be achieved.

Impact

This bug can have the following impacts on the Boost protocol:

Unpredictable Rewards: Users cannot anticipate the exact reward amount due to the potential for unintended reward resets, leading to confusion and reduced trust.

Exploitation Potential: A malicious actor might try to take advantage of the reward reset mechanic to repeatedly claim rewards close to the rewardDecay value.

Scenario

Let's imagine a boost with an initialReward of 1000 tokens and a rewardDecay of 100 tokens. After several claims, the currentReward drops to 50 tokens. The next user to claim should receive 50 tokens, and the currentReward should be set to 0. However, due to the bug, the currentReward would be incorrectly set back to 100 tokens.

Fix

The fix involves correcting the assignment of cgdaParams.currentReward when reward is less than rewardDecay.

Modified claim Function:

function claim(address claimTarget, bytes calldata) external virtual override onlyOwner returns (bool) {
 // ... other logic ...

  // Calculate the current reward and update the state
 uint256 reward = currentReward();
 cgdaParams.lastClaimTime = block.timestamp;
 cgdaParams.currentReward =
   reward > cgdaParams.rewardDecay ? reward - cgdaParams.rewardDecay : reward; // Correct assignment

 // ... transfer logic ...
}

By changing cgdaParams.rewardDecay to reward in the last line, we ensure the currentReward is set to the correct remaining balance, even when it's lower than the rewardDecay amount.