Core Contracts

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

Decimal Mismatch in StabilityPool

Summary

The StabilityPool's token conversion functions use incorrect decimal scaling, allowing attackers to manipulate DEToken minting/burning ratios when rToken and DEToken have different decimal places.

Vulnerability Details

calculateDeCRVUSDAmount and calculateRcrvUSDAmount use incorrect scaling if rToken/DEToken decimals differ.

StabilityPool.sol#calculateDeCRVUSDAmount

StabilityPool.sol#calculateRcrvUSDAmount

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

See this attack Path:

  1. Deposit rToken (18 decimals)

  2. Receive inflated DEToken amount (6 decimals)

  3. Exploit decimal mismatch for profit

  4. Drain pool through redemptions

Impact

Incorrect minting/burning of DEToken, leading to loss of funds.

Tools Used

manual

Recommendations

Use WadRayMath for precise scaling and validate token decimal compatibility. Here's the correct implementation using WadRayMath for precise decimal handling

function calculateDeCRVUSDAmount(uint256 rcrvUSDAmount) public view returns (uint256) {
// Normalize to WAD (18 decimals)
uint256 normalizedAmount = WadRayMath.wadMul(
rcrvUSDAmount,
10 ** (18 - rTokenDecimals)
);
// Apply exchange rate
uint256 exchangeAdjusted = WadRayMath.wadDiv(
normalizedAmount,
getExchangeRate()
);
// Scale to DEToken decimals
return exchangeAdjusted / (10 ** (18 - deTokenDecimals));
}
function calculateRcrvUSDAmount(uint256 deCRVUSDAmount) public view returns (uint256) {
// Normalize to WAD
uint256 normalizedAmount = WadRayMath.wadMul(
deCRVUSDAmount,
10 ** (18 - deTokenDecimals)
);
// Apply exchange rate
uint256 exchangeAdjusted = WadRayMath.wadMul(
normalizedAmount,
getExchangeRate()
);
// Scale to rToken decimals
return exchangeAdjusted / (10 ** (18 - rTokenDecimals));
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month 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.