Summary
A vulnerability exists in the lending pool protocol where there is no enforced minimum position size for borrowing. The protocol allows creating arbitrarily small positions with minimal collateral, potentially leading to dust positions.
Vulnerability Details
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();
ReserveLibrary.updateReserveState(reserve, rateData);
_ensureLiquidity(amount);
uint256 userTotalDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex) + amount;
if (collateralValue < userTotalDebt.percentMul(liquidationThreshold)) {
revert NotEnoughCollateralToBorrow();
}
uint256 scaledAmount = amount.rayDiv(reserve.usageIndex);
(bool isFirstMint, uint256 amountMinted, uint256 newTotalSupply) = IDebtToken(reserve.reserveDebtTokenAddress).mint(msg.sender, msg.sender, amount, reserve.usageIndex);
IRToken(reserve.reserveRTokenAddress).transferAsset(msg.sender, amount);
user.scaledDebtBalance += scaledAmount;
reserve.totalUsage = newTotalSupply;
ReserveLibrary.updateInterestRatesAndLiquidity(reserve, rateData, 0, amount);
_rebalanceLiquidity();
emit Borrow(msg.sender, amount);
}
The borrow function allows users to create positions with any amount greater than 0 , calculated using the fomula:
Maximum borrow = collateralValue / 0.8 (with liquidationThreshold = 80_00)
No minimumThreshold is enforced for either collateral or borrow amount.
Example a user can borrow 1 wei worth of collateral and borrow 1.25 wei.
code snippet displaying the issue
modifier onlyValidAmount(uint256 amount) {
if (amount == 0) revert InvalidAmount();
_;
}
Impact
Small underwater positions may never be liquidated because the gas cost of liquidation exceeds the potential profit from the liqidation. This creates permanent bad debt for the protocol, as liquidators have no economic incentive to clear these positions. For example, if a position has:
Tools Used
Manual review
Recommendations
uint256 public constant MIN_COLLATERAL_VALUE = 1e18;
uint256 public constant MIN_BORROW_AMOUNT = 1e17;
function borrow(uint256 amount) external {
require(amount >= MIN_COLLATERAL_VALUE, " Borrow amount too small");
require (getCollateralValue(msg.sender) >= MIN_COLLATERAL_VALUE, "Insufficient collateral");
}
2. Implement dust collection mechanism for all existing small positions.