Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Valid

In `StabilityPool`, wrong logic in `calculateRaacRewards()` could result in DRAINING all the `RAAC` rewards from the Pool

Summary

The logic in calculateRaacRewards() makes use of the WHOLE userDeposit, for the computation of raac rewards, which is wrong.

A person with HUGE funds in StabilityPool , can make multiple withdrawals with dust amount, and each time, claim rewards on his large deposit, which would result in draining all the RAAC reward which belongs to other users, from the protocol.

Vulnerability Details

The withdraw() function lets user withdraw their rTokens by depositing deTokens in the StabilityPool.

During withdrawal, it computes RAAC rewards belonging to the User via calculateRaacRewards()

The portion of rewards to be given, depends upon the Total Deposit made by the user.

#calculateRaacRewards()

#withdraw()

function calculateRaacRewards(address user) public view returns (uint256) {
uint256 userDeposit = userDeposits[user];
uint256 totalDeposits = deToken.totalSupply();
uint256 totalRewards = raacToken.balanceOf(address(this));
if (totalDeposits < 1e6) return 0;
return (totalRewards * userDeposit) / totalDeposits;
}

Notice that, we use userDeposits[user] to compute the RAAC rewards(raac token) to be given to the user.
This reward amount is then simply transferred from StabilityPool to the user later in withdraw()

However, there lies is an issue in this logic for reward calculation.

We consider the user's TOTAL DEPOSIT, but we do NOT consider "How much ?" he is withdrawing using withdraw(), which leads to inaccurate reward calculation.

Reason being, a person can choose to withdraw only 1 rToken, and he'll get rewards based on his total deposit.

Suppose, he has HUGE number of rTokens in the pool, he can make multiple withdrawals using dust amount, and take all the rewards i.e. totalRewards from stabilityPool.

For example, Consider this scenario:

  1. A user has deposited 100,000 rTokens in a pool with 1,000,000 total deposits

  2. The reward pool contains 50,000 RAAC tokens(Rewards)

  3. The user initiates a withdrawal of just 1 rToken

  4. He will receive rewards calculated as: 50,000 * 100,000 / 1,000,000 = 5,000 RAAC tokens

  5. The user can repeat this process with another 1 rToken withdrawal

  6. For the second withdrawal, they receive: 45,000 * 100,000 / 1,000,000 = 4,500 RAAC tokens

He can repeat the process which will allow him to take out all the rewards through multiple small withdrawals, while maintaining a HIGH deposit to claim LARGE portion of remaining rewards.

Because there is no time interval, another issue that can arise is that, a user can repeatedly make an instant deposit,and withdrawal, which results in similar situation(losing raac rewards).

Impact

Malicious user can extract more rewards than intended.

The stabilityPool RAAC rewards can be drained through small withdrawals.

Tools Used

Manual

Recommendations

Avoid using userDeposit for computation of rewards. Consider adding a logic which limits the user from withdrawing a higher portion of rewards than intended.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

StabilityPool::withdraw can be called with partial amounts, but it always send the full rewards

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!