Core Contracts

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

Failure to Update Reserve Interests Before Prime Rate Adjustment

Summary

According to the natspec of the updateReserveInterests the function should be called before any operation that changes the state of the reserve how ever this function was not called when setting a new prime rate for the reserve which inherently changes the state of the reserve in the function setPrimeRate

Vulnerability Details

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/libraries/pools/ReserveLibrary.sol#L115-L148
https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L674-L680
https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/oracles/RAACPrimeRateOracle.sol#L26-L41

The setPrimeRate function modifies the reserve's interest rate parameters without first calling updateReserveInterests. This omission means that any accrued interest since the last update is not accounted for before changing the prime rate. Since updateReserveInterests is responsible for updating the liquidity and usage indices based on the elapsed time, skipping it results in stale indices being used in subsequent calculations.

Impact

  1. Operations relying on the liquidity or usage index after setPrimeRate will use outdated values

  2. Borrowers will be affected as the protocol will calculate interest based on outdated indices.

Tools Used

Manual Review

Recommendations

Call the updateReserveInterests before setting a new prime rate.

/**
* @notice Sets a new prime rate for the reserve.
* @param reserve The reserve data.
* @param rateData The reserve rate parameters.
* @param newPrimeRate The new prime rate (in RAY).
*/
//@audit does not call updateReserveInterests(reserve, rateData);
function setPrimeRate( ReserveData storage reserve,ReserveRateData storage rateData,uint256 newPrimeRate) internal {
updateReserveInterests(reserve, rateData);
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();
}
rateData.primeRate = newPrimeRate;
updateInterestRatesAndLiquidity(reserve, rateData, 0, 0);
emit PrimeRateUpdated(oldPrimeRate, newPrimeRate);
}
Updates

Lead Judging Commences

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

ReserveLibrary fails to update reserve state before changing rate parameters (prime rate, protocol fee rate), causing new rates to be applied retroactively to interest since last update

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

ReserveLibrary fails to update reserve state before changing rate parameters (prime rate, protocol fee rate), causing new rates to be applied retroactively to interest since last update

Support

FAQs

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

Give us feedback!