Core Contracts

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

LendingPool's borrow() function permits borrowing up to 80% (liquidationThreshold) of collateral value

Summary

The LendingPool contract's collateralization checks allow users to borrow up to the full liquidation threshold, creating positions that are immediately vulnerable to liquidation. This design flaw undermines the protocol's risk management.

Vulnerability Details

The LendingPool's borrow() function permits borrowing up to 80% (liquidationThreshold) of collateral value: LendingPool#L344-L345

// Current implementation
// Ensure the user has enough collateral to cover the new debt
if (collateralValue < userTotalDebt.percentMul(liquidationThreshold)) {
revert NotEnoughCollateralToBorrow();
}

See this flow, a user deposits 100 ETH as collateral when ETH = $2000. They can borrow up to 80% ($160,000). If ETH drops just 1% to $1980, their position becomes liquidatable, as their collateral value ($198,000) falls below the required threshold.

Because the borrow() function uses the liquidation threshold directly as the borrowing limit, rather than maintaining a safety buffer between the maximum borrow amount and the liquidation threshold.

userTotalDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex) + amount
collateralValue < userTotalDebt.percentMul(liquidationThreshold)

Impact

This vulnerability creates systemic risk by allowing positions to be created at the liquidation threshold, making them immediately vulnerable to market volatility. Users can borrow up to exactly 80% of their collateral value, making them immediately vulnerable to liquidation if prices decline even slightly.

Recommendations

contract LendingPool {
// Add safety margin below liquidation threshold
uint256 constant SAFETY_MARGIN = 5_00; // 5% buffer
uint256 constant BORROW_THRESHOLD = liquidationThreshold - SAFETY_MARGIN;
function borrow() external {
// Use lower threshold for new borrows
if (collateralValue < userTotalDebt.percentMul(BORROW_THRESHOLD)) {
revert NotEnoughCollateralToBorrow();
}
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month 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.