Core Contracts

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

ReserveLibrary: Incorrect Utilization Rate Calculation When Reserve is Empty

Summary

The ReserveLibrary::calculateUtilizationRate function in the ReserveLibrary returns an incorrect utilization rate of 100% (represented as RAY) when both totalLiquidity and totalDebt are zero. This flaw leads to distorted interest rate calculations, impacting the protocol’s economic logic.

Vulnerability Details

The function calculateUtilizationRate is designed to compute the ratio of borrowed funds to the total available liquidity. However, it contains a flawed edge-case check:

function calculateUtilizationRate(uint256 totalLiquidity, uint256 totalDebt) internal pure returns (uint256) {
if (totalLiquidity < 1) {
return WadRayMath.RAY; // Returns 100% utilization if liquidity is zero
}
return totalDebt.rayDiv(totalLiquidity + totalDebt);
}

When totalLiquidity and totalDebt are both zero (e.g., in a newly created reserve), the function incorrectly returns RAY (100% utilization). This occurs because the check totalLiquidity < 1 triggers a return of RAY without verifying whether totalDebt is also zero.

Impact

  • Distorted Interest Rates: The protocol will calculate excessively high borrow rates (usageRate) and liquidity rates (liquidityRate) for empty reserves, deterring users.

  • Protocol Fee Extraction: Fees may be charged on non-existent debt, eroding trust in the protocol.

  • Attack Vector: An attacker could create empty reserves to manipulate global interest rate calculations or trigger unintended protocol behavior.

Tools Used

  • Manual Code Review: The issue was identified through a line-by-line audit of the ReserveLibrary logic.

Recommendations

  1. Fix the Edge-Case Logic:
    Update the calculateUtilizationRate function to handle the totalLiquidity == 0 and totalDebt == 0 case explicitly:

    function calculateUtilizationRate(uint256 totalLiquidity, uint256 totalDebt) internal pure returns (uint256) {
    if (totalLiquidity == 0) {
    return (totalDebt == 0) ? 0 : WadRayMath.RAY;
    }
    return totalDebt.rayDiv(totalLiquidity + totalDebt);
    }
  2. Add Unit Tests:
    Implement tests for the following scenarios:

    • totalLiquidity = 0, totalDebt = 0 → utilization = 0%.

    • totalLiquidity = 0, totalDebt > 0 → utilization = 100%.

    • Non-zero liquidity and debt → utilization = debt / (liquidity + debt).

  3. Document the Behavior:
    Clarify in the code comments and protocol documentation how utilization is calculated for edge cases (e.g., empty reserves).

  4. Monitor Reserves:
    Implement safeguards to prevent the creation of reserves with invalid initial parameters (e.g., zero liquidity and debt).

This fix ensures accurate interest rate calculations and maintains the protocol’s economic integrity.

Updates

Lead Judging Commences

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

ReserveLibrary::calculateUtilizationRate returns 100% when both liquidity and debt are zero, causing artificially high interest rates at pool initialization

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

ReserveLibrary::calculateUtilizationRate returns 100% when both liquidity and debt are zero, causing artificially high interest rates at pool initialization

Support

FAQs

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