Core Contracts

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

Users can use flashloan to take the raac reward in the stability pool

Summary

A user can take a flashloan deposit rtokens and get DECRVUSD and immediately withdraw to get the raac rewards in the stability contract. These rewards serve as an incentive to liquidity providers, but an attacker can profit by using flashloan to take as many rewards as possible from the pool.

Vulnerability Details

In the code there is no time constraint to prevent a flashloan attack in the stability pool .

user takes a flashloan gets rtoken deposit and withdraws in the same block.

/**
* @notice Allows a user to deposit rToken and receive deToken.
* @param amount Amount of rToken to deposit.
*/
function deposit(uint256 amount) external nonReentrant whenNotPaused validAmount(amount) {
_update();
rToken.safeTransferFrom(msg.sender, address(this), amount);
uint256 deCRVUSDAmount = calculateDeCRVUSDAmount(amount);
deToken.mint(msg.sender, deCRVUSDAmount); // de token miniting
userDeposits[msg.sender] += amount;
_mintRAACRewards(); ///what happens if address 0.
emit Deposit(msg.sender, amount, deCRVUSDAmount);
}

Based on the withdrawal process the user gets rewards based on what was deposited, hence allowing an attacker to deposit and withdraw rewards meant for liquidity providers

function withdraw(uint256 deCRVUSDAmount) external nonReentrant whenNotPaused validAmount(deCRVUSDAmount) {
_update();
if (deToken.balanceOf(msg.sender) < deCRVUSDAmount) revert InsufficientBalance();
uint256 rcrvUSDAmount = calculateRcrvUSDAmount(deCRVUSDAmount);
@audit>>> uint256 raacRewards = calculateRaacRewards(msg.sender); //bug calculate based on rtoken or dtoken not both 2 different scaling bro
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);
@audit>>> if (raacRewards > 0) {
@audit>>> raacToken.safeTransfer(msg.sender, raacRewards); //sending less reward or 0 rewards when user earned for providing liquidity
}
emit Withdraw(msg.sender, rcrvUSDAmount, deCRVUSDAmount, raacRewards);
}
/**
* @notice Calculates the pending RAAC rewards for a user.
* @param user Address of the user.
* @return Amount of RAAC rewards.
*/
function calculateRaacRewards(address user) public view returns (uint256) {
uint256 userDeposit = userDeposits[user];
uint256 totalDeposits = deToken.totalSupply();
@audit>>> uint256 totalRewards = raacToken.balanceOf(address(this));
if (totalDeposits < 1e6) return 0;
@audit>>> return (totalRewards * userDeposit) / totalDeposits;
}

Impact

With flashloan or a lot of funds, an attacker can steal the raac rewards to be distributed to liquidity providers.

Tools Used

Manual review

Recommendations

Implement a time lock for liquidity providers or allow reward calculation only when the user has deposited over a certain period of time.

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 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.