Skip to content

Latest commit

 

History

History
98 lines (65 loc) · 3.12 KB

092.md

File metadata and controls

98 lines (65 loc) · 3.12 KB

Tiny Licorice Loris

Medium

Users can stall liquidations by depleting their collateralAtoken Bal to 0

Summary

Users can stall liquidations when the liquidator sets params.receiveAToken to false

https://github.com/sherlock-audit/2025-01-aave-v3-3/blob/main/aave-v3-origin/src/contracts/protocol/libraries/logic/LiquidationLogic.sol#L384

Root Cause

Whenever a liquidator sets params.receiveAToken to false, Users can make the liquidation tx to revert.

This is due to the below check in ScaledBalanceTokenBase._burnScaled(),

uint256 amountScaled = amount.rayDiv(index);
    require(amountScaled != 0, Errors.INVALID_BURN_AMOUNT);

when vars.collateralAToken.burn is called in LiquidationLogic._burnCollateralATokens(), ScaledBalanceTokenBase._burnScaled() is called.

vars.collateralAToken.burn(
      params.user,
      msg.sender,
      vars.actualCollateralToLiquidate,
      collateralReserveCache.nextLiquidityIndex
    );

The issue here is that vars.actualCollateralToLiquidate will be 0 if user's collateral balance is 0.

see LiquidationLogic._calculateAvailableCollateralToLiquidate()

  function _calculateAvailableCollateralToLiquidate(
    DataTypes.ReserveConfigurationMap memory collateralReserveConfiguration,
    uint256 collateralAssetPrice,
    uint256 collateralAssetUnit,
    uint256 debtAssetPrice,
    uint256 debtAssetUnit,
    uint256 debtToCover,
    uint256 userCollateralBalance,
    uint256 liquidationBonus
  ) internal pure returns (uint256, uint256, uint256, uint256) {
    AvailableCollateralToLiquidateLocalVars memory vars;
    vars.collateralAssetPrice = collateralAssetPrice;
    vars.liquidationProtocolFeePercentage = collateralReserveConfiguration
      .getLiquidationProtocolFee();

    // This is the base collateral to liquidate based on the given debt to cover
    vars.baseCollateral =
      ((debtAssetPrice * debtToCover * collateralAssetUnit)) /
      (vars.collateralAssetPrice * debtAssetUnit);

    vars.maxCollateralToLiquidate = vars.baseCollateral.percentMul(liquidationBonus);

    if (vars.maxCollateralToLiquidate > userCollateralBalance) {
      vars.collateralAmount = userCollateralBalance;//@audit here
      vars.debtAmountNeeded = ((vars.collateralAssetPrice * vars.collateralAmount * debtAssetUnit) /
        (debtAssetPrice * collateralAssetUnit)).percentDiv(liquidationBonus);
    } else {

Internal Pre-conditions

  1. Atokens can be transferred. which they can https://aave.com/docs/developers/smart-contracts/tokenization#atoken

External Pre-conditions

  1. User transfers out his collateral balance depleting it to 0 when his position becomes liquidatable.

Attack Path

  1. User takes positions
  2. User's positions become unhealthy and liquidateable
  3. just before liquidator liquidates his position, he transfers out all his collateral balance
  4. liquidator attempts to liquidate user's positions but it reverts.

Impact

Users can stall liquidations by depleting their collateralAtoken Bal to 0

PoC

No response

Mitigation

look for a way to prevent users from being able to move their collateral balance