Skip to content

FLO-13: Fee collection drains reserves below seize amount, causing revert #222

Open

Description

@liobrasil

Severity: Medium

Files Affected

  • cadence/contracts/FlowALPv1.cdc

Description

When _borrowUpdatedTokenState is called (line 1911 in manualLiquidation), it triggers updateForTimeChange() which calls collectInsurance and collectStability. Both functions withdraw from the token's reserves: // collectInsurance, line 1112: let withdrawn <- reserves.withdraw(amount: withdrawAmountU64) // collectStability, line 1176: let withdrawn <- reserves.withdraw(amount: withdrawAmountU64) These withdrawals occur before the liquidation's own withdrawal from reserves at _doLiquidation line 2015: let seizedVault <- self._withdrawFromReserves(type: seizeType, amount: seizeAmount) If the combined insurance + stability fee collection reduces the seize token's reserves below seizeAmount, the liquidation reverts. This is particularly dangerous because:

  • The fee collection is time-dependent — the longer since the last update, the larger the fees
  • A position could be liquidatable and have sufficient reserves, but the _borrowUpdatedTokenState call that checks its health also drains the reserves needed for liquidation
  • This creates a race condition: the first liquidation attempt after a long idle period is most likely to fail

Recommendation

Either (a) check that reserves remain sufficient for pending liquidations before fee collection, (b) cap fee collection to leave a minimum reserve buffer, or (c) allow fee collection to be deferred if reserves are below a threshold.


Parent Issue: #209

Activity

  1. holyfuchs commented on Mar 13, 2026

    @holyfuchs
    Contributor

    This behavior is as designed. In the system, both fee collection and withdrawals (including liquidations) draw from the same reserves, and it is a fundamental property that not all withdrawal requests can necessarily be processed immediately if liquidity is insufficient.

    As a result, liquidation withdrawals are not prioritized over other reserve-consuming operations such as fee collection. If reserves are temporarily insufficient, the operation may revert and can be retried once liquidity becomes available. For this reason, we consider this a non-issue rather than a vulnerability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions