Core Contracts

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

Hardcoded exchange rate in Stability Pool prevents proper value accrual

Summary

The StabilityPool contract uses a hardcoded 1:1 exchange rate between rToken and deToken, ignoring the actual value relationship between these tokens. This prevents proper value accrual for Stability Pool depositors and could lead to unfair value extraction when depositing or withdrawing from the pool.


Vulnerability Details

The StabilityPool's getExchangeRate() function is hardcoded to return 1e18 (1.0 in WAD precision):

function getExchangeRate() public view returns (uint256) {
// uint256 totalDeCRVUSD = deToken.totalSupply();
// uint256 totalRcrvUSD = rToken.balanceOf(address(this));
// if (totalDeCRVUSD == 0 || totalRcrvUSD == 0) return 10**18;
// uint256 scalingFactor = 10**(18 + deTokenDecimals - rTokenDecimals);
// return (totalRcrvUSD * scalingFactor) / totalDeCRVUSD;
return 1e18;
}

This hardcoded rate is used in both deposit and withdrawal calculations:

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;
}

The RToken contract shows that rToken balances increase over time due to interest accrual through the liquidity index. However, the hardcoded exchange rate in StabilityPool means this value accrual is not reflected in the conversion between rToken and deToken.

Impact

This vulnerability has significant economic implications:

The hardcoded 1:1 exchange rate means that late depositors to the Stability Pool receive the same amount of deTokens per rToken as early depositors, despite early depositors' rTokens having accrued more value through interest. This creates unfair value distribution and could lead to:

  1. Earlier depositors being disincentivized to maintain their deposits as they don't benefit from their rToken's interest accrual

  2. Late depositors receiving more value than they should by depositing rTokens after significant interest has accrued

  3. Potential for value extraction by depositing and withdrawing at strategic times to capture interest accrual without proper price adjustment

Recommendations

Implement the originally intended dynamic exchange rate calculation that was commented out:

function getExchangeRate() public view returns (uint256) {
- return 1e18;
+ uint256 totalDeCRVUSD = deToken.totalSupply();
+ uint256 totalRcrvUSD = rToken.balanceOf(address(this));
+ if (totalDeCRVUSD == 0 || totalRcrvUSD == 0) return 10**18;
+
+ uint256 scalingFactor = 10**(18 + deTokenDecimals - rTokenDecimals);
+ return (totalRcrvUSD * scalingFactor) / totalDeCRVUSD;
}
Updates

Lead Judging Commences

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