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:
76: uint256 public constant BASE_LIQUIDATION_THRESHOLD = 80 * 1e2;
...:
...:
...:
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:
295: ReserveLibrary.updateReserveState(reserve, rateData);
296:
297:
298: uint256 userDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex);
299: uint256 collateralValue = getUserCollateralValue(msg.sender);
300: uint256 nftValue = getNFTPrice(tokenId);
301:
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) {
...:
...:
...:
343:
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();
}