Core Contracts

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

User can steal all of the `RAACToken` rewards in `StabilityPool`

Summary

The way that rewards are distributed is the root cause of this issue

Vulnerability Details

By taking a look at the StabilityPool::withdraw function, we see that first calculates the rewards and then transfers them:

function withdraw(
uint256 deCRVUSDAmount
) external nonReentrant whenNotPaused validAmount(deCRVUSDAmount) {
_update();
if (deToken.balanceOf(msg.sender) < deCRVUSDAmount)
revert InsufficientBalance();
uint256 rcrvUSDAmount = calculateRcrvUSDAmount(deCRVUSDAmount);
@> uint256 raacRewards = calculateRaacRewards(msg.sender);
if (userDeposits[msg.sender] < rcrvUSDAmount)
revert InsufficientBalance();
userDeposits[msg.sender] -= rcrvUSDAmount;
if (userDeposits[msg.sender] == 0) {
delete userDeposits[msg.sender];
}
deToken.burn(msg.sender, deCRVUSDAmount);
rToken.safeTransfer(msg.sender, rcrvUSDAmount);
if (raacRewards > 0) {
@> raacToken.safeTransfer(msg.sender, raacRewards);
}
emit Withdraw(msg.sender, rcrvUSDAmount, deCRVUSDAmount, raacRewards);
}

This is good but the way that reward are calculated, allows a user to steal all of the RAACToken balance of the contract by doing the following attack:

  1. Malicious user sees that the contract has a big RAACToken balance and deposits

  2. Then immediately withdraws which will give him a big share of the rewards because of the following way rewards are calculated (They are strictly dependant on the user's balance, the total supply of deToken, the number of rewards and nothing more):

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;
}
  1. Then he can just repeat those actions until the contract is practically drained of RAACToken rewards

Impact

User can steal all of the RAACToken rewards from StabilityPool

Tools Used

Manual Review

Recommendations

Add some time based mechanism to the reward calculation so it is not profitable for the user to just deposit and withdraw right away.

Updates

Lead Judging Commences

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

StabilityPool::calculateRaacRewards is vulnerable to just in time deposits

Support

FAQs

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

Give us feedback!