Core Contracts

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

Updating the prime rate will change the interest for a time that was already passed

Summary

Updating the prime rate will change the interest for a time that was already passed

Vulnerability Details

setPrimeRate doesn't update the interest before setting the new price.

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/libraries/pools/ReserveLibrary.sol#L399-L414

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();
}
//@audit M should have updated rates before setting this rate
// not whis will overcompound for time that it wasn't active
rateData.primeRate = newPrimeRate;
updateInterestRatesAndLiquidity(reserve, rateData, 0, 0);
emit PrimeRateUpdated(oldPrimeRate, newPrimeRate);
}

This will mean that if the lat update was at time T and prime is updated at T+1day, even though it is updated now it would take account for all of the interest generated between T and T+1day, aka. it will change the rate for time that has already passed.

Impact

Updating the price will change rates for a time that has already passed. That is not good as it would cause an instant spike or decrease and internal accounting errors as some function take the rate without updating it, like getNormalizedDebt.

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;
}
// (e^((currentUsageRate * 1e27 / 1 year) * timeDelta / 1e27)) * reserve.usageIndex / 1e27
return calculateCompoundedInterest(rateData.currentUsageRate, timeDelta).rayMul(reserve.usageIndex);
}

Tools Used

Manual review

Recommendations

Update the rates before changing the prime rate.

+ updateInterestRatesAndLiquidity(reserve, rateData, 0, 0);
rateData.primeRate = newPrimeRate;
- updateInterestRatesAndLiquidity(reserve, rateData, 0, 0);
Updates

Lead Judging Commences

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

Give us feedback!