Core Contracts

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

Vulnerability Allowing Flash Loan Attack to Steal All RAAC Rewards

Summary

The StabilityPool lacks a time tracking mechanism for deposits and withdrawals, allowing a malicious user to exploit this by executing a flash loan attack. This vulnerability enables the attacker to drain the full RAAC rewards from the pool without holding any long-term deposits.

Vulnerability Details

In the current implementation of the StabilityPool, both the deposit() and withdraw() functions do not track the time associated with user deposits or withdrawals. This oversight allows an attacker to manipulate the reward distribution as follows:

Code Snippets

The withdraw() function does not incorporate any time-based checks:

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); // Rewards calculated without time consideration
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);
}

Attack Path

  1. The attacker takes out a flash loan to acquire rToken from the LendingPool.

  2. They deposit the rToken into the StabilityPool.

  3. Immediately after depositing, the attacker calls withdraw(), receiving the full RAAC rewards calculated based on the total deposits, without any time-based restrictions.

  4. The attacker repays the flash loan, all within a single transaction.

The reward calculation in calculateRaacRewards() is based on the total deposits without considering the duration of the deposit:

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; // No time tracking
}

Impact

This vulnerability allows an attacker to drain the RAAC rewards from the stability pool through a flash loan attack, potentially leading to significant financial losses for the protocol and its users. The lack of a time-based mechanism undermines the integrity of the reward distribution model.

Tools Used

  • Manual Review

Recommendations

To mitigate this vulnerability, it is essential to implement a time tracking mechanism for deposits and withdrawals in the StabilityPool. This mechanism should ensure that rewards are calculated based on the duration for which the funds are held in the pool.

Updates

Lead Judging Commences

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