Core Contracts

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

User can drain all RAAC reward tokens from stabilityPool

Summary

Every time user withdraw his RTokens from stabilityPool he is getting his portion of RAAC tokens reward. But this mechanism can be easily abused.

Vulnerability Details

User can withdraw portion of his tokens, and then rewards are calculated in following formula.

// StabilityPool.sol 224
function withdraw(uint256 deCRVUSDAmount) external nonReentrant whenNotPaused validAmount(deCRVUSDAmount) {
...
uint256 raacRewards = calculateRaacRewards(msg.sender);
...
if (raacRewards > 0) {
raacToken.safeTransfer(msg.sender, raacRewards);
}
}
// StabilityPool.sol 251
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;
}

Let's assume following scenario:

  • RToken totalSupply: 10000

  • RAACToken 500

  • Mike deposited 1000 RTokens

(small number for simplicity)

Mike withdraws 1 RToken, base on formula above, he will get (500 * 1000) / 10000 = 50 RAACTokens

Then he is triggering the same transaction many times:

  • (450 * 999) / 9999 = 44.95 RAACTokens

  • (405.05 * 998) / 9998 = 40.43 RAACTokens

  • ...

Mike might wait for new reward distribution and trigger as many transactions as it is required to steal all the tokens, while fair system would distribute to Mike only 50 RAACTokens, which is 10% of total reward, since Mike owns 10% of totalSupply.

Even if nobody is abusing it intentionaly, that solution wouldn't make any sense, because it is rewarding often withdrawals, not the time of participating in deposit.

Impact

Someone could steal the entire RAAC token distribution, leaving nothing for the rest.

Tools Used

Manual Review

Recommendation

Reward system should takes into account time of participaion, and it should allow to claim again the same reward

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!