Core Contracts

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

Inverted Scaling Factor in StabilityPool Withdrawal Calculation Breaks Deposit/Withdrawal Parity

Summary

The withdrawal calculation in StabilityPool.sol uses an inverted decimal scaling formula compared to deposits, enabling users to withdraw incorrect rToken amounts. This fundamental arithmetic error destroys the core value preservation guarantee of the StabilityPool when rToken/deToken have different decimals.

Vulnerability Details

The vulnerability stems from mismatched scaling factors between deposit and withdrawal calculations:

Deposit Calculation (calculateDeCRVUSDAmount):

uint256 scalingFactor = 10 ** (18 + deTokenDecimals - rTokenDecimals);
return (rcrvUSDAmount * scalingFactor) / getExchangeRate();

Withdrawal Calculation (calculateRcrvUSDAmount):

uint256 scalingFactor = 10 ** (18 + rTokenDecimals - deTokenDecimals); // INVERTED
return (deCRVUSDAmount * getExchangeRate()) / scalingFactor;

The withdrawal calculation reverses the decimal adjustment order, creating an asymmetric scaling relationship. This error persists regardless of specific decimal values when deTokenDecimals ≠ rTokenDecimals.

Example

Let's demonstrate the issue with specific values:

  • deTokenDecimals = 18, rTokenDecimals = 6

  • User deposits 100 rTokens (100e6)

1. Deposit Flow (calculateDeCRVUSDAmount):

scalingFactor = 10^(18 + 18 - 6) = 10^30
deTokens = (100e6 * 10^30) / 1e18 = 100e18 deTokens
  • we mint to the user : 100e18 deTokens
    2. Withdrawal Flow (calculateRcrvUSDAmount):

scalingFactor = 10^(18 + 6 - 18) = 10^6 // INCORRECT! Formula is flipped
rTokens = (100e18 * 1e18) / 10^6 = 100e30 rTokens

The Issue:

  • User deposited 100e6 rTokens

  • User received 100e18 deTokens (correct conversion)

  • User attempts to withdraw 100e18 deTokens

  • User receives 100e30 rTokens (24 orders of magnitude more!)

This happens because:

  1. The deposit correctly scales up by multiplying with a large factor (10^30)

  2. The withdrawal incorrectly scales down by dividing by a small factor (10^6)

  3. The formulas should be inverses of each other, but flipping the subtraction in the exponent breaks this relationship

Impact

could lead to permanently locks funds by DoSing withdrawals, or allows complete protocol fund drainage

Tools Used

  • Foundry

  • Manual Review

Recommendations

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

This change aligns the withdrawal scaling with the deposit calculation, maintaining consistent decimal handling across both operations regardless of specific decimal values.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Incorrect scaling factor formula in StabilityPool::calculateRcrvUSDAmount function

Both tokens have 18 decimals. Info

Support

FAQs

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

Give us feedback!