Core Contracts

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

Incorrect liquidity index and usage index calculation when oracle updates the prime rate

Summary

When setting a new prime rate it calculates the liquidity and usage indexes using a delta of time that belongs to the old prime rate.

Vulnerability Details

When the oracle sets a new prime rate in LendingPool.sol#setPrimeRate it calls the ReserveLibrary.setPrimeRate function that actually sets the new prime and then in ReserveLibrary#updateInterestRatesAndLiquidity calculates using the new prime the rateData.currentUsageRate and the rateData.currentLiquidityRate fields what will be used in the ReserveLibrary#updateReserveInterests function to calculate the new liquidity and usage indexes but the problem is that the indexes use a delta of time between the last update and the current block, check the following code: uint256 timeDelta = block.timestamp - uint256(reserve.lastUpdateTimestamp);

The delta of time is really important here because the problem is that is doing the updating of indexes with the new prime rate but the delta of time belongs to the previous old prime rate, that is because it should call reserve#updateReserveInterests before setting the new prime rate, but it is not doing it.

Impact

The incorrect calculation of the liquidity and usage index will impact almost every important function of the lending pool,

Operation Reason
Borrow Mixed usageIndex
Repay Mixed usageIndex
Liquidation Mixed Both usageIndex and liquidationIndex
Deposit Mixed liquidityIndex
Withdraw Mixed liquidityIndex
withdrawNFT Mixed usageIndex

Tools Used

  • VS Code

Recommendations

In order to calculate properly the indexes first calculate using the old prime and then set the new one, so the delta of time will be fresh:

function setPrimeRate( ReserveData storage reserve,ReserveRateData storage rateData,uint256 newPrimeRate) internal {
if (newPrimeRate < 1) revert PrimeRateMustBePositive();
updateReserveInterests(reserve, rateData); //@auditor calculate first the indexes with old prime rate and his intermediate values
uint256 oldPrimeRate = rateData.primeRate;
if (oldPrimeRate > 0) {
uint256 maxChange = oldPrimeRate.percentMul(500);
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);
}
Updates

Lead Judging Commences

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

setPrimeRate applies new rates retroactively by updating rates after changing primeRate, causing incorrect interest calculations for past periods

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

setPrimeRate applies new rates retroactively by updating rates after changing primeRate, causing incorrect interest calculations for past periods

Support

FAQs

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