Core Contracts

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

Incorrect Scaling Factor in Withdrawal Conversion

Summary

The calculateRcrvUSDAmount function applies incorrect scaling formulae when converting deToken back to rToken.When rTokenDecimals < deTokenDecimals, users may receive significantly more rTokens than expected while burning only a small amount of deToken and in most cases DOS users due to InsufficientBalance check.When rTokenDecimals > deTokenDecimals, users will burn their deTokens but receive no rTokens due to rounding resulting in a loss of funds.

Vulnerability Details

calculateRcrvUSDAmount uses this code to convert deToken to equivalent rToken

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

If rTokenDecimals < deTokenDecimals, the scaling factor is too small making the returned rToken amount too large therefore users will attempt withdrawing disproportionate value of rToken

If rTokenDecimals > deTokenDecimals, the scaling factor is too large making the returned rToken amount too small, causing users to receive fewer tokens than they should or even 0 tokens.

Scenario 1: Overwithdrawal (rTokenDecimals = 6, deTokenDecimals = 18)

User has 100 deToken.
getExchangeRate() returns 1e18 (1:1 ratio).
Expected withdrawal: 100 rToken (which has 6 decimals).

Current Calculation:

scalingFactor = 10^(18 + 6 - 18) = 10^6
rTokenAmount = (100 * 10¹⁸ * 10¹⁸) / 10
= 100 * 10³⁰
= 1e32

User receives 1e32 rToken instead of 1e8 .This most likely DOS the user due to sufficient balance checks in the withdrawal or still user withdraws a disproportional amount which later leads to Dos for future withdrawals.

Scenario 2: Underwithdrawal (rTokenDecimals = 18, deTokenDecimals = 6)

Setup:
User has 100 rToken (which has 18 decimals).
getExchangeRate() returns 1e18 (1:1 ratio).
Expected withdrawal: 100 rToken.

scalingFactor = 10^(18 + 18 - 6) = 10³⁰
rTokenAmount = (100 * getExchangeRate()) / scalingFactor
= (100 * 10¹⁸) / 10³⁰
= 1e8 * 1e18 / 10³⁰
= 1e-4

user burns their deTokens but receives no rTokens in return. This scenario causes complete loss of funds for the user

Impact

  • users receive disproportionately large rToken withdrawals potentially causing a Denial of Service (DOS).

  • Users can receive no rTokens while burning deTokens incase of scenario 2.

Tools Used

Manual review

Recommendations

Update the calculateRcrvUSDAmount function to use the correct scaling factor:

function calculateRcrvUSDAmount(uint256 deCRVUSDAmount) public view returns (uint256) {
// Correct scaling factor calculation
uint256 scalingFactor = 10**(18 + deTokenDecimals - rTokenDecimals);
return (deCRVUSDAmount * getExchangeRate()) / scalingFactor;
}
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!