Core Contracts

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

`ReserveLibrary.getNormalizedDebt` doesn't return normalized debt

Summary

The ReserveLibrary.getNormalizedDebt function should return normalized debt, however it returns current usageIdex.

Vulnerability Details

The following ReserveLibrary.getBorrowRate(), ReserveLibrary.getLiquidityRate() retrieves totalDebt from ReserveLibrary.getNormalizedDebt function and totalDebt refers to total normalized debt.

function getBorrowRate(ReserveData storage reserve,ReserveRateData storage rateData) internal view returns (uint256) {
>> uint256 totalDebt = getNormalizedDebt(reserve, rateData);
uint256 utilizationRate = calculateUtilizationRate(reserve.totalLiquidity, totalDebt);
return calculateBorrowRate(rateData.primeRate, rateData.baseRate, rateData.optimalRate, rateData.maxRate, rateData.optimalUtilizationRate, utilizationRate);
}
function getLiquidityRate(ReserveData storage reserve,ReserveRateData storage rateData) internal view returns (uint256) {
>> uint256 totalDebt = getNormalizedDebt(reserve, rateData);
uint256 utilizationRate = calculateUtilizationRate(reserve.totalLiquidity, totalDebt);
return calculateLiquidityRate(utilizationRate, rateData.currentUsageRate, rateData.protocolFeeRate, totalDebt);
}

However, ReserveLibrary.getNormalizedDebt function doesn't return total normalized debt. It returns the current usageIdex. This could result incorrect calculation for utilizationRate.

utilizationRate is used for base calculations of the library and this impacts to entire calculations of library.

/**
* @notice Gets the normalized debt of the reserve.
* @param reserve The reserve data.
* @return The normalized debt (in underlying asset units).
*/
function getNormalizedDebt(ReserveData storage reserve, ReserveRateData storage rateData) internal view returns (uint256) {
uint256 timeDelta = block.timestamp - uint256(reserve.lastUpdateTimestamp);
if (timeDelta < 1) {
return reserve.totalUsage;
}
@> return calculateCompoundedInterest(rateData.currentUsageRate, timeDelta).rayMul(reserve.usageIndex);
}

Impact

The several calculations such as rateData.currentUsageRate and rateData.currentLiquidityRate will be incorrect and breaks the protocol's sustainability.

Tools Used

Manual Review

Recommendations

Multiply reserve.totalUsage to the return value:

/**
* @notice Gets the normalized debt of the reserve.
* @param reserve The reserve data.
* @return The normalized debt (in underlying asset units).
*/
function getNormalizedDebt(ReserveData storage reserve, ReserveRateData storage rateData) internal view returns (uint256) {
uint256 timeDelta = block.timestamp - uint256(reserve.lastUpdateTimestamp);
if (timeDelta < 1) {
return reserve.totalUsage;
}
- return calculateCompoundedInterest(rateData.currentUsageRate, timeDelta).rayMul(reserve.usageIndex);
+ uint256 currentUsageIndex = calculateCompoundedInterest(rateData.currentUsageRate, timeDelta).rayMul(reserve.usageIndex);
+ return reserve.totalUsage.rayMul(currentUsageIndex);
}
Updates

Lead Judging Commences

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

getNormalizedDebt doesn't return total debt but only the index, causing incorrect utilization and interest rate calculations

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

getNormalizedDebt doesn't return total debt but only the index, causing incorrect utilization and interest rate calculations

Support

FAQs

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