Core Contracts

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

`LendingPool` Constructor Only checks If `_initialPrimeRate` Is Not Zero But Doesn't Make Sure RAY

Summary

The LendingPool constructor has a flaw where it does not make sure the prime rate is RAY based which if not, there is no recovery to increase it without redeployment.

Vulnerability Details

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L185)

The constructor is only checking that it is not 0:

constructor(
address _reserveAssetAddress,
address _rTokenAddress,
address _debtTokenAddress,
address _raacNFTAddress,
address _priceOracleAddress,
uint256 _initialPrimeRate
) Ownable(msg.sender) {
if (
_reserveAssetAddress == address(0) ||
_rTokenAddress == address(0) ||
_debtTokenAddress == address(0) ||
_raacNFTAddress == address(0) ||
_priceOracleAddress == address(0) ||
_initialPrimeRate == 0
) revert AddressCannotBeZero();

If at deployment you don't pass in a RAY amount you are forced to redeploy due to the 5% limit on change of primeRate which is not acheivable:

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L679)

We call LendingPool::setPrimeRate to change the primeRate which calls the ReserveLibrary::setPrimeRate

function setPrimeRate(uint256 newPrimeRate) external onlyPrimeRateOracle {
ReserveLibrary.setPrimeRate(reserve, rateData, newPrimeRate);
}

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/libraries/pools/ReserveLibrary.sol#L404C2-L408C10)

Inside ReserveLibrary.setPrimeRate there is a check that you can only change primeRate by 5%:

if (oldPrimeRate > 0) {
@> uint256 maxChange = oldPrimeRate.percentMul(500); // Max 5% change
uint256 diff = newPrimeRate > oldPrimeRate ? newPrimeRate - oldPrimeRate : oldPrimeRate - newPrimeRate;
@> if (diff > maxChange) revert PrimeRateChangeExceedsLimit();
}

Impact

If the initial prime rate is set to a non-RAY value (not 1e27) during deployment, there is no recovery mechanism since:

  1. The prime rate can only be changed by 5% at a time through setPrimeRate

  2. To reach RAY (1e27) from a much lower value would require a massive amount incremental changes

  3. The only solution would be to redeploy the entire lending pool contract

  4. This causes significant operational overhead and requires complex migration procedures

Tools Used

Foundry

Recommendations

Add a validation check in the constructor to ensure the initial prime rate is RAY-based:

constructor(
address _reserveAssetAddress,
address _rTokenAddress,
address _debtTokenAddress,
address _raacNFTAddress,
address _priceOracleAddress,
uint256 _initialPrimeRate
) Ownable(msg.sender) {
if (
_reserveAssetAddress == address(0) ||
_rTokenAddress == address(0) ||
_debtTokenAddress == address(0) ||
_raacNFTAddress == address(0) ||
_priceOracleAddress == address(0) ||
+ _initialPrimeRate == 0 ||
+ _initialPrimeRate < 1e27 // Add check for RAY-based value
) revert AddressCannotBeZero();
// ... rest of constructor
}

Additionally, consider updating the ReserveLibrary.setPrimeRate function to include the same validation:

function setPrimeRate(
ReserveData storage reserve,
ReserveRateData storage rateData,
uint256 newPrimeRate
) internal {
- if (newPrimeRate < 1) revert PrimeRateMustBePositive();
+ if (newPrimeRate < 1e27) revert PrimeRateMustBePositive();
// ... rest of function
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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