Core Contracts

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

Unauthorized Fund Drain via `withdraw()` Allowing Users to Claim More Than Deposited

The withdraw() function is designed to allow users to redeem their deposited rToken by burning an equivalent amount of deToken. However, due to incorrect calculation of redeemable rToken amounts, a user could withdraw more rToken than they originally deposited, leading to an unauthorized drain of funds from the Stability Pool. The problem originates in the calculateRcrvUSDAmount() function:

function calculateRcrvUSDAmount(uint256 deCRVUSDAmount) public view returns (uint256) {
uint256 scalingFactor = 10**(18 + rTokenDecimals - deTokenDecimals);
return (deCRVUSDAmount * getExchangeRate()) / scalingFactor;
}

The issue occurs if getExchangeRate() is manipulated or fluctuates significantly. Since the exchange rate is used to determine the amount of rToken a user can withdraw per deToken, an attacker can artificially inflate getExchangeRate() (e.g. through flash loans, governance attacks, or external market manipulations). If getExchangeRate() increases significantly, the function will compute a much higher rToken amount than the user actually deposited. As a result, when withdraw() is executed:

uint256 rcrvUSDAmount = calculateRcrvUSDAmount(deCRVUSDAmount);
if (userDeposits[msg.sender] < rcrvUSDAmount) revert InsufficientBalance();
userDeposits[msg.sender] -= rcrvUSDAmount;

The check userDeposits[msg.sender] < rcrvUSDAmount is ineffective because the user may have deposited a much lower amount initially but can withdraw significantly more due to the exchange rate shift. This allows attackers to systematically drain Stability Pool reserves by repeatedly depositing rToken when the exchange rate is low and withdrawing disproportionately high amounts when the rate spikes.

Impact

Attackers can withdraw more rToken than they initially deposited, leading to an unauthorized fund drain from the Stability Pool, potentially exhausting liquidity and destabilizing the protocol.

Mitigation

Ensure getExchangeRate() is updated correctly and resistant to manipulation, and introduce a mechanism to cap withdrawals to the original deposit amount per user to prevent abuse.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!