Core Contracts

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

Incorrect Undercollateralization Check in LendingPool::withdrawNFT() and LendingPool::borrow() functions

Summary

The withdrawNFT() and borrow() functions in the LendingPool contract contain an incorrect collateralization check, allowing users to withdraw or borrow more than their effective collateral value (collateralValue * liquidationThreshold). This flaw creates an opportunity for users to manipulate their collateral and debt levels, increasing the risk of bad debt for the protocol.

Vulnerability Details

The withdrawNFT() function allows users to withdraw NFTs they have deposited as collateral. To prevent users from becoming undercollateralized after withdrawal, the function includes the following check:

if (collateralValue - nftValue < userDebt.percentMul(liquidationThreshold)) {
revert WithdrawalWouldLeaveUserUnderCollateralized();
}

This check is incorrect because it applies the liquidation threshold to userDebt rather than the user's remaining collateral. As a result, users can withdraw NFTs while appearing to satisfy the condition, even though their remaining collateral is insufficient to cover their outstanding debt. A similar issue exists in the borrow() function, allowing users to borrow more than their collateral can safely support.

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();
// Update reserve state before borrowing
ReserveLibrary.updateReserveState(reserve, rateData);
// Ensure sufficient liquidity is available
_ensureLiquidity(amount);
// Fetch user's total debt after borrowing
uint256 userTotalDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex) + amount; // @audit doesn't account for balance increase
// Ensure the user has enough collateral to cover the new debt
if (collateralValue < userTotalDebt.percentMul(liquidationThreshold)) { // @audit Incorrect Undercollateralization check
revert NotEnoughCollateralToBorrow();
}
...........
}

Impact

This vulnerability poses a critical risk to the protocol, as it directly affects the enforcement of collateralization requirements. If exploited, it allows borrowers to withdraw NFTs while leaving insufficient collateral to support their outstanding debt, potentially leading to situations where liquidations cannot recover the full amount owed. This increases the likelihood of lenders and liquidity providers bearing losses, ultimately threatening the protocol’s stability.

Tools Used

Manual Review

Recommendations

To correctly enforce collateral requirements, the flawed check should be replaced with the following:

// withdrawNFT() function
if ((collateralValue - nftValue).percentMul(liquidationThreshold) < userDebt) { // @audit Incorrect Undercollateralization check
revert WithdrawalWouldLeaveUserUnderCollateralized();
}
// borrow() function
if ((collateralValue).percentMul(liquidationThreshold) < userDebt) { // @audit Incorrect Undercollateralization check
revert NotEnoughCollateralToBorrow();
}
Updates

Lead Judging Commences

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

LendingPool::borrow as well as withdrawNFT() reverses collateralization check, comparing collateral < debt*0.8 instead of collateral*0.8 > debt, allowing 125% borrowing vs intended 80%

Support

FAQs

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