Core Contracts

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

Invalid Utilization Rate When Reserve is Empty

Summary

The utilization rate measures how much of the reserve's liquidity is being "used" (i.e., borrowed). It is calculated as: [ \text{Utilization Rate} = \frac{\text{Total Debt}}{\text{Total Liquidity} + \text{Total Debt}} ]

Expressed in RAY (27 decimal) precision. A 100% utilization rate (WadRayMath.RAY) means all liquidity is borrowed.

Vulnerability Details

The current implementation of calculateUtilizationRate has a flawed edge-case check

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

When both totalLiquidity and totalDebt are zero (e.g., a newly created reserve with no deposits or borrows), the function incorrectly returns 100% utilization.

The check totalLiquidity < 1 triggers when totalLiquidity == 0, but it doesn't account for totalDebt also being zero.

A 100% utilization rate causes the protocol to calculate excessively high borrow rates (via calculateBorrowRate), even though the reserve is empty.

Example:

A new reserve with 0 liquidity and 0 debt would have maximum borrow rates, deterring users from participating.

Impact

Misleading rates disrupt the protocol's economic incentives, leading to unexpected behavior

Tools Used

Foundry

Recommendations

Update the edge-case logic to handle the scenario where both totalLiquidity and totalDebt are zero.

function calculateUtilizationRate(uint256 totalLiquidity, uint256 totalDebt) internal pure returns (uint256) {
if (totalLiquidity == 0 && totalDebt == 0) {
return 0; // 0% utilization when reserve is empty
}
if (totalLiquidity == 0) {
return WadRayMath.RAY; // 100% utilization if liquidity is 0 but debt exists
}
return totalDebt.rayDiv(totalLiquidity + totalDebt);
}
Updates

Lead Judging Commences

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