Core Contracts

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

Missing Reserve Interest Update in setPrimeRate: Inconsistent Interest Accrual and Lending Protocol Risks

Summary

In the ReserveLibrary of the RAAC lending protocol, the setPrimeRate function is responsible for updating the prime rate of the reserve, which is a critical input for calculating interest rates for borrowing and lending. However, the function fails to update the accrued reserve interest when a new prime rate is set. Specifically, it omits the call to update reserve interests (e.g., via an updateReserveInterests function) before or during the update. As a result, the internal state that tracks accrued interest remains based on the old prime rate, leading to inconsistencies in interest calculations and potential economic distortions. This misalignment can cause severe issues in interest accrual, mispricing of loans, and unintended incentives in the lending protocol.

Vulnerability Details

How It Begins

  • Function Flow:
    The setPrimeRate function accepts a new prime rate and performs a check to ensure the change does not exceed a maximum allowed difference (5% change). It then updates the primeRate in the ReserveRateData and calls updateInterestRatesAndLiquidity to propagate changes. However, it omits updating the reserve interest accrual itself (i.e., it does not call an updateReserveInterests function).

    function setPrimeRate(ReserveData storage reserve, ReserveRateData storage rateData, uint256 newPrimeRate)
    internal
    {
    if (newPrimeRate < 1) revert PrimeRateMustBePositive();
    // Forgot to update reserve interest: updateReserveInterests is not called here
    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);
    }
  • Impact on Consistency:
    By not updating the reserve interest, the protocol fails to reflect the effect of the new prime rate on accrued interest. This creates an inconsistency: while the prime rate in rateData is updated, the interest accumulated on outstanding loans remains based on the previous rate. Over time, this misalignment can lead to significant errors in interest calculations, affecting both lenders and borrowers.

Consequences

  • Incorrect Interest Accrual:
    The reserve interest will continue to accrue based on the outdated prime rate, leading to miscalculation of interest payments. This could result in either undercharging or overcharging borrowers, distorting the incentive structure.

  • Economic Distortion:
    Inaccurate interest rates affect the profitability of loans and the yield received by lenders, potentially destabilizing the lending market and undermining the protocol's economic model.

  • Potential for Exploitation:
    If the discrepancy between the new prime rate and the accrued interest is significant, sophisticated users may exploit this misalignment to manipulate loan terms or arbitrage between markets.

Impact

  • Inconsistent Interest Accrual:
    The prime rate update does not trigger an update to accrued interest, causing discrepancies between the configured rate and the actual interest charged or earned.

  • Mispricing of Loans:
    Borrowers may be charged incorrect interest amounts, and lenders may receive yields that do not reflect current market conditions.

  • Economic Instability:
    Over time, the failure to correctly update interest accrual can lead to systemic economic imbalances, reducing the protocol's reliability and attractiveness.

  • Exploitation Risk:
    Sophisticated actors may exploit the mismatch between the new prime rate and stale accrued interest to gain arbitrage opportunities or manipulate loan terms.

Tools Used

  • Manual Review

  • Foundry

Recommendations

To ensure consistency and correctness in interest calculations, the setPrimeRate function should be modified to update the reserve interest immediately when the prime rate changes. This can be achieved by incorporating a call to an updateReserveInterests function before or during the prime rate update.

Proposed Diff for setPrimeRate

function setPrimeRate(ReserveData storage reserve, ReserveRateData storage rateData, uint256 newPrimeRate)
internal
{
if (newPrimeRate < 1) revert PrimeRateMustBePositive();
+ // Update reserve interest based on the current state before changing the prime rate.
+ updateReserveInterests(reserve, rateData);
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:

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!