Core Contracts

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

Denial of service in Lending pool as the new prime rate may be higher than the maximum rate

Summary

Reserve prime rate can be higher than the max rate as it can be updated by the Prime Rate Oracle without validation. This may result in a permanent Denial of Service issue in the Lending Pool processes.

Vulnerability Details

Prime Rate Oracle is allowed to update the reserve prime rate by calling the LendingPool::setPrimeRate function, which in turn calls the ReserveLibrary::setPrimeRate function. However, when setting the new value, it is not checked against the maximum rate value, which may be exceeded causing a Denial of Service in the functions that change the system global state, since processes will revert in the ReserveLibrary::calculateBorrowRate function.

ReserveLibrary::calculateBorrowRate internal function is called by ReserveLibrary::updateInterestRatesAndLiquidity, which in turn is called after any operation changes the liquidity or debt of the reserve, as documentation states.

> ReserveLibrary.sol
function setPrimeRate( ReserveData storage reserve,ReserveRateData storage rateData,uint256 newPrimeRate) internal {
if (newPrimeRate < 1) revert PrimeRateMustBePositive();
uint256 oldPrimeRate = rateData.primeRate;
// @audit - Only checked the maximum change of 5% per call.
// However, check against maximum rate is missing.
if (oldPrimeRate > 0) {
uint256 maxChange = oldPrimeRate.percentMul(500); // Max 5% change
uint256 diff = newPrimeRate > oldPrimeRate ? newPrimeRate - oldPrimeRate : oldPrimeRate - newPrimeRate;
if (diff > maxChange) revert PrimeRateChangeExceedsLimit();
}
rateData.primeRate = newPrimeRate;
updateInterestRatesAndLiquidity(reserve, rateData, 0, 0);
emit PrimeRateUpdated(oldPrimeRate, newPrimeRate);
}
> ReserveLibrary.sol
function calculateBorrowRate(
uint256 primeRate,
uint256 baseRate,
uint256 optimalRate,
uint256 maxRate,
uint256 optimalUtilizationRate,
uint256 utilizationRate
) internal pure returns (uint256) {
@> if (primeRate <= baseRate || primeRate >= maxRate || optimalRate <= baseRate || optimalRate >= maxRate) {
// @audit - process will revert if primeRate >= maxRate
revert InvalidInterestRateParameters();
}
... snip
}

Impact

Impact: High

Likelihood: Low

Tools Used

Manual Review

Recommendations

Perform a check of the new prime rate against the max rate in ReserveLibrary::setPrimeRate.

> ReserveLibrary.sol
function setPrimeRate( ReserveData storage reserve,ReserveRateData storage rateData,uint256 newPrimeRate) internal {
if (newPrimeRate < 1) revert PrimeRateMustBePositive();
uint256 oldPrimeRate = rateData.primeRate;
if (oldPrimeRate > 0) {
uint256 maxChange = oldPrimeRate.percentMul(500); // Max 5% change
uint256 diff = newPrimeRate > oldPrimeRate ? newPrimeRate - oldPrimeRate : oldPrimeRate - newPrimeRate;
if (diff > maxChange) revert PrimeRateChangeExceedsLimit();
}
+ if (newPrimeRate > rateData.maxRate){
+ newPrimeRate = rateData.maxRate;
+ }
rateData.primeRate = newPrimeRate;
updateInterestRatesAndLiquidity(reserve, rateData, 0, 0);
emit PrimeRateUpdated(oldPrimeRate, newPrimeRate);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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