Summary
LendingPool::borrow() allows users to borrow reserve assets using their NFT collateral, however the function incorrectly calculates the total debt of a user before allowing borrowing. The amount
parameter, representing the new borrow amount, is not properly scaled before being added to the user's total debt, leading to an inaccurate debt calculation.
Vulnerability Details
In the borrow
function, the total user debt is calculated as follows:
[contracts/core/pools/LendingPool/LendingPool.sol]
325 function borrow(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
326 if (isUnderLiquidation[msg.sender]) revert CannotBorrowUnderLiquidation();
327
328 UserData storage user = userData[msg.sender];
329
330 uint256 collateralValue = getUserCollateralValue(msg.sender);
331
332 if (collateralValue == 0) revert NoCollateral();
333
334
335 ReserveLibrary.updateReserveState(reserve, rateData);
336
337
338 _ensureLiquidity(amount);
339
340
341 -> uint256 userTotalDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex) + amount;
342
343
344 if (collateralValue < userTotalDebt.percentMul(liquidationThreshold)) {
345 revert NotEnoughCollateralToBorrow();
346 }
347
348
349 uint256 scaledAmount = amount.rayDiv(reserve.usageIndex);
350
351
352
353 (bool isFirstMint, uint256 amountMinted, uint256 newTotalSupply) = IDebtToken(reserve.reserveDebtTokenAddress).mint(msg.sender, msg.sender, amount, reserve.usageIndex);
354
355
356 IRToken(reserve.reserveRTokenAddress).transferAsset(msg.sender, amount);
357
358 user.scaledDebtBalance += scaledAmount;
359
360 reserve.totalUsage = newTotalSupply;
361
362
363 ReserveLibrary.updateInterestRatesAndLiquidity(reserve, rateData, 0, amount);
364
365
366 _rebalanceLiquidity();
367
368 emit Borrow(msg.sender, amount);
369 }
However user.scaledDebtBalance
is stored in a scaled format (i.e., divided by usageIndex
).
Adding amount
directly without scaling results in an underestimated total debt. This could allow users to borrow more than their collateral allows, bypassing lending constraints.
Impact
Users are able to borrow more than their collateral allows, increasing the risk of insolvency.
Recommendations
Modify the total debt calculation to properly scale amount before adding it.
- uint256 userTotalDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex) + amount;
+ uint256 scaledAmount = amount.rayDiv(reserve.usageIndex);
+ uint256 userTotalDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex) + scaledAmount;