Core Contracts

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

Incorrect state update order in borrow(), LendingPool.sol

Summary

The borrow function allows users to borrow reserve assets using their NFT collateral. However, some state-updating functions are executed after the external call to transferAsset, which can lead to incorrect debt and inconsistencies calculations in the protocol.

Vulnerability Details

function borrow(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
if (isUnderLiquidation[msg.sender]) revert CannotBorrowUnderLiquidation();
UserData storage user = userData[msg.sender];
uint256 collateralValue = getUserCollateralValue(msg.sender);
if (collateralValue == 0) revert NoCollateral();
ReserveLibrary.updateReserveState(reserve, rateData);
_ensureLiquidity(amount);
uint256 userTotalDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex) + amount; // wrong
if (collateralValue < userTotalDebt.percentMul(liquidationThreshold)) {
revert NotEnoughCollateralToBorrow();
}
uint256 scaledAmount = amount.rayDiv(reserve.usageIndex);
(bool isFirstMint, uint256 amountMinted, uint256 newTotalSupply) =
IDebtToken(reserve.reserveDebtTokenAddress).mint(msg.sender, msg.sender, amount, reserve.usageIndex);
// Transfer borrowed amount to user
IRToken(reserve.reserveRTokenAddress).transferAsset(msg.sender, amount);
// @ audit state appdates after external call
user.scaledDebtBalance += scaledAmount;
reserve.totalUsage = newTotalSupply;
// @ audit state appdates after external call
ReserveLibrary.updateInterestRatesAndLiquidity(reserve, rateData, 0, amount);
// @ audit state appdates after external call
_rebalanceLiquidity();
emit Borrow(msg.sender, amount);
}

The following operations are performed aftertransferAsset leading to incorrect calculations and reentrancy attacks.

// @ audit state appdates after external call
user.scaledDebtBalance += scaledAmount;
reserve.totalUsage = newTotalSupply;
// @ audit state appdates after external call
ReserveLibrary.updateInterestRatesAndLiquidity(reserve, rateData, 0, amount);
// @ audit state appdates after external call
_rebalanceLiquidity();

These updates should be done before the external call to ensure proper execution flow.

Incorrect Debt Tracking, Users might borrow more than their collateral allows because debt updates happen after the actual borrowing succeeds.

The user’s total debt is calculated after the asset is transferred, which may result in an incorrect liquidation assessment

Impact

Borrowers might be able to borrow more than they should.

Liquidity pool imbalances could occur due to incorrect _ensureLiquidity(amount) checks.

Tools Used

Manual review

Recommendations

To fix this issue, state updates should be performed before the external transfer call (transferAsset) succeeds.

Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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