Core Contracts

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

Missing update of base, optimal, and max rates

Summary

The ReserveLibrary#setPrimeRate() updates the primeRate but does not update the dependent rates (baseRate, optimalRate, maxRate). Since these values are calculated based on primeRate in LendingPool's constructor, but not updated when primeRate changes, the borrow rate calculation can become inconsistent or incorrect.

Vulnerability Details

LendingPool#setPrimeRate() is called by oracle and it is perfomed by ReserveLibrary#setPrimeRate()

But in this function(), only primeRate is updated and other relation rates(baseRate, optimalRate, maxRate) are not updated.

constructor(
address _reserveAssetAddress,
address _rTokenAddress,
address _debtTokenAddress,
address _raacNFTAddress,
address _priceOracleAddress,
uint256 _initialPrimeRate
) Ownable(msg.sender) {
...
// Prime Rate
rateData.primeRate = uint256(_initialPrimeRate);
rateData.baseRate = rateData.primeRate.percentMul(25_00); // 25% of prime rate
rateData.optimalRate = rateData.primeRate.percentMul(50_00); // 50% of prime rate
rateData.maxRate = rateData.primeRate.percentMul(400_00); // 400% of prime rate
...
}

As seen above in LendingPool's constructor, when primeRate is set, other rates are updated based on this value.

There's no set function in this protocol.

Since calculateBorrowRate() still uses old baseRate, optimalRate, and maxRate values, it results in incorrect borrow rate calculations.

This can cause:

  • Undercharging borrowers, leading to reduced lending pool earnings.

  • Overcharging borrowers, making borrowing unattractive or unprofitable.

  • Unintended behavior in interest rate adjustments.

Impact

Financial imbalance in the lending pool: Borrowers may pay less or more than intended, affecting the sustainability of the protocol.

It will lead to potential loss of liquidity. If borrowing is too cheap, bad debt increases; if too expensive, demand decreases.

Tools Used

manual

Recommendations

Update dependent rates inside ReserveLibrary#setPrimeRate() same as LendingPool's constructor.

function setPrimeRate(
ReserveData storage reserve,
ReserveRateData storage rateData,
uint256 newPrimeRate
) internal {
if (newPrimeRate < 1) revert PrimeRateMustBePositive();

function setPrimeRate(
ReserveData storage reserve,
ReserveRateData storage rateData,
uint256 newPrimeRate
) internal {
...
rateData.primeRate = newPrimeRate;
+ rateData.baseRate = newPrimeRate.percentMul(25_00); // 25% of prime rate
+ rateData.optimalRate = newPrimeRate.percentMul(50_00); // 50% of prime rate
+ rateData.maxRate = newPrimeRate.percentMul(400_00); // 400% of prime rate
...
}

}

Updates

Lead Judging Commences

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

ReserveLibrary::setPrimeRate only updates primeRate without adjusting baseRate, optimalRate, and maxRate proportionally, breaking interest rate model and causing incorrect calculations

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

ReserveLibrary::setPrimeRate only updates primeRate without adjusting baseRate, optimalRate, and maxRate proportionally, breaking interest rate model and causing incorrect calculations

Support

FAQs

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