Core Contracts

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

Incorrect Utilization Rate Calculation Due to Misuse of Normalized Debt Value

Summary

The RAACMinter contract calculates the system utilization rate using the value returned by lendingPool.getNormalizedDebt(), which actually returns the usageIndex (in RAY, or 1e27 precision) instead of the true debt value. This miscalculation results in an erroneously high utilization rate, thereby triggering inappropriate emission rate adjustments.

Vulnerability Details

The utilization rate in the RAACMinter contract is computed as follows:

function getUtilizationRate() internal view returns (uint256) {
uint256 totalBorrowed = lendingPool.getNormalizedDebt();
uint256 totalDeposits = stabilityPool.getTotalDeposits();
if (totalDeposits == 0) return 0;
return (totalBorrowed * 100) / totalDeposits;
}
  • LendingPool Implementation:
    The getNormalizedDebt() function in the LendingPool contract returns reserve.usageIndex, which is initialized as follows in the constructor:

    reserve.usageIndex = uint128(WadRayMath.RAY); // 1e27

    This usageIndex is maintained in RAY precision and does not represent the actual debt value.

  • Correct Debt Value:
    The actual debt value is stored in reserve.totalUsage in the ReserveData structure:

    struct ReserveData {
    // ...
    uint256 totalUsage;
    uint128 liquidityIndex;
    uint128 usageIndex;
    // ...
    }

    Using usageIndex instead of totalUsage leads to an incorrect calculation.

  • Emission Rate Adjustment:
    The computed utilization rate is then used in the calculateNewEmissionRate() function:

uint256 public adjustmentFactor = 5; // 5% adjustment per update
uint256 public utilizationTarget = 70; // 70% target utilization
function calculateNewEmissionRate() internal view returns (uint256) {
uint256 utilizationRate = getUtilizationRate();
uint256 adjustment = (emissionRate * adjustmentFactor) / 100;
@>> if (utilizationRate > utilizationTarget) {
uint256 increasedRate = emissionRate + adjustment;
uint256 maxRate = increasedRate > benchmarkRate ? increasedRate : benchmarkRate;
return maxRate < maxEmissionRate ? maxRate : maxEmissionRate;
} else if (utilizationRate < utilizationTarget) {
uint256 decreasedRate = emissionRate > adjustment ? emissionRate - adjustment : 0;
uint256 minRate = decreasedRate < benchmarkRate ? decreasedRate : benchmarkRate;
return minRate > minEmissionRate ? minRate : minEmissionRate;
}
return emissionRate;
}

Proof-of-Concept (POC)

  1. Initial Conditions:

    • Assume lendingPool.getNormalizedDebt() returns 1e27 (the initial usageIndex).

    • Assume stabilityPool.getTotalDeposits() returns 100e18 (representing 100 tokens with 18 decimals).

  2. Expected Calculation:

    • If the actual borrowed amount were 50 tokens, the correct utilization rate should be:

      (50e18 * 100) / 100e18 = 50%
  3. Actual Calculation with Current Implementation:

    • The utilization rate is computed as:

      (1e27 * 100) / 100e18 = (1e27 * 100) / 1e20 = 1e7 = 10,000,000%
    • This result is many orders of magnitude higher than expected, leading the system to believe that utilization is excessively high.

  4. Emission Adjustment Impact:
    Given the utilization target is 70% and the adjustment factor is 5%, the erroneous high utilization rate would trigger the logic in calculateNewEmissionRate() to increase or cap the emission rate at the maximum allowed, resulting in unintended token emission levels.

Impact

  • The inflated utilization rate can trigger inappropriate adjustments to the emission rate, potentially resulting in drastic changes to token minting.

  • The utilization rate is vastly overestimated, which could lead to an incorrect adjustment of the emission rate.

Tools Used

Manual Review

Recommendations

Update the getUtilizationRate() function to use the actual debt value (reserve.totalUsage) instead of the usageIndex. This will ensure accurate utilization calculations and proper emission rate adjustments.

Updates

Lead Judging Commences

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

RAACMinter::getUtilizationRate incorrectly mixes stability pool deposits with lending pool debt index instead of using proper lending pool metrics

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

RAACMinter::getUtilizationRate incorrectly mixes stability pool deposits with lending pool debt index instead of using proper lending pool metrics

Support

FAQs

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