Core Contracts

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

`LendingPool::WithdrawNFT` and `LendingPool::borrow` collateralization check is wrong

Summary

The collateralization is wrong and allow to borrow more than the deposited collateral

Vulnerability details

The check wrongly multiply the debt value by the liquidationThrehsold which is equal to 80%, reducing the value of the debt during the check, while it should have reduced the value of the collateral instead:

File: contracts/core/pools/LendingPool/LendingPool.sol
75: // Liquidation parameters
76: uint256 public constant BASE_LIQUIDATION_THRESHOLD = 80 * 1e2; // 80% in basis points
...:
...: //* ------------------ some code ------------------ *//
...:
288: function withdrawNFT(uint256 tokenId) external nonReentrant whenNotPaused {
289: if (isUnderLiquidation[msg.sender]) revert CannotWithdrawUnderLiquidation();
290:
291: UserData storage user = userData[msg.sender];
292: if (!user.depositedNFTs[tokenId]) revert NFTNotDeposited();
293:
294: // update state
295: ReserveLibrary.updateReserveState(reserve, rateData);
296:
297: // Check if withdrawal would leave user undercollateralized
298: uint256 userDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex);
299: uint256 collateralValue = getUserCollateralValue(msg.sender);
300: uint256 nftValue = getNFTPrice(tokenId);
301: //issue: if new collateral value < debt * 80%
302: if (collateralValue - nftValue < userDebt.percentMul(liquidationThreshold)) {
303: revert WithdrawalWouldLeaveUserUnderCollateralized();
304: }

Same issue is present in borrow

File: contracts/core/pools/LendingPool/LendingPool.sol
325: function borrow(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
...:
...: //* ------------------ some code ------------------ *//
...:
343: // Ensure the user has enough collateral to cover the new debt
344: if (collateralValue < userTotalDebt.percentMul(liquidationThreshold)) {
345: revert NotEnoughCollateralToBorrow();
346: }

Impact

Users can borrow more than their collateral should allow to.

Recommended Mitigation Steps

function withdrawNFT(uint256 tokenId) external nonReentrant whenNotPaused {
if (isUnderLiquidation[msg.sender]) revert CannotWithdrawUnderLiquidation();
//* ------------------ some code ------------------ *//
- if (collateralValue - nftValue < userDebt.percentMul(liquidationThreshold)) {
+ uint256 newCollateralValue = collateralValue - nftValue;
+ if (newCollateralValue.percentMul(liquidationThreshold) < userDebt) {
revert WithdrawalWouldLeaveUserUnderCollateralized();
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 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.