Core Contracts

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

Value Lock in Stability Pool Due to Incorrect Handling of RToken Transfers

Description:

The Stability Pool allows users to deposit RTokens at a fixed 1:1 ratio to mint deCRVUSD. However, RTokens increase in value over time relative to their underlying asset. The RToken transferFrom and transfer functions operate based on the underlying asset amount rather than the absolute RToken amount, meaning that transferring an underlying amount results in a different quantity of RTokens being moved.

When a user deposits into the Stability Pool using safeTransferFrom, the transferred amount is stored as their deposit. However, over time, as the RToken value increases, the amount withdrawable remains fixed at the originally deposited amount. Any excess value accumulated by the RTokens in the contract cannot be withdrawn by the user, leading to value being locked permanently within the Stability Pool.

Steps to Reproduce:

  1. Assume 1 RToken = 1 underlying token at the time of deposit.

  2. User deposits 10 RTokens (transferring 10 underlying tokens).

  3. Over time, the value of 1 RToken increases to 1.5 underlying tokens.

  4. When withdrawing, the user can only withdraw 10 RTokens, despite their actual value being 15 underlying tokens.

  5. The additional 5 underlying tokens worth of RTokens remain locked in the contract.

Exploit Scenario:

  • A user deposits RTokens into the Stability Pool.

  • The value of RTokens appreciates over time.

  • The user attempts to withdraw but can only retrieve the originally deposited amount.

  • The difference between the appreciated value and the original deposit remains locked in the contract indefinitely.

Recommendation:

  • Instead of storing deposits as raw amounts, track the deposited amount in terms of RTokens relative to their underlying value at the time of withdrawal.

  • Use an updated conversion mechanism that accounts for the changing value of RTokens over time.

  • Implement a mechanism to withdraw the full proportionate value of RTokens based on their latest valuation instead of the initially deposited amount.

Affected Code:

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);
userDeposits[msg.sender] += amount; // Incorrect tracking
_mintRAACRewards();
emit Deposit(msg.sender, amount, deCRVUSDAmount);
}
function withdraw(uint256 deCRVUSDAmount) external nonReentrant whenNotPaused validAmount(deCRVUSDAmount) {
_update();
if (deToken.balanceOf(msg.sender) < deCRVUSDAmount) revert InsufficientBalance();
uint256 rcrvUSDAmount = calculateRcrvUSDAmount(deCRVUSDAmount);
if (userDeposits[msg.sender] < rcrvUSDAmount) revert InsufficientBalance();
userDeposits[msg.sender] -= rcrvUSDAmount; // Does not account for value appreciation
deToken.burn(msg.sender, deCRVUSDAmount);
rToken.safeTransfer(msg.sender, rcrvUSDAmount); // Withdraws fixed amount, losing appreciation
emit Withdraw(msg.sender, rcrvUSDAmount, deCRVUSDAmount, 0);
}
Updates

Lead Judging Commences

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

StabilityPool::getExchangeRate hardcodes 1:1 ratio instead of calculating real rate, enabling unlimited deToken minting against limited reserves

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

StabilityPool::getExchangeRate hardcodes 1:1 ratio instead of calculating real rate, enabling unlimited deToken minting against limited reserves

Support

FAQs

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

Give us feedback!