56757 sc high incorrect leftover collateral check blocks liquidator fee payment leading broken incentives delayed deleveraging

Submitted on Oct 20th 2025 at 12:42:31 UTC by @yesofcourse for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #56757

  • Report Type: Smart Contract

  • Report severity: High

  • Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol

  • Impacts:

    • Temporary freezing of funds for at least 1 hour

Description

Brief/Intro

In AlchemistV3._doLiquidation, the protocol debits the gross seized collateral (including the liquidator’s base fee) from the victim, then always forwards the net amount to the Transmuter-but only pays the base fee to the liquidator if the account still has “leftover” collateral after that gross debit.

When the seizure consumes all collateral (common), the fee is withheld, making liquidations uneconomic. Reduced liquidator participation leads to stalled deleveraging, which can temporarily freeze user funds that depend on liquidations to proceed.

Vulnerability Details

src/AlchemistV3.sol, liquidation path inside _doLiquidation(...).

What happens :

Why this is a bug

  • The base fee is part of the gross seizure already removed from the victim. Payment to the liquidator should not depend on any post-seizure “leftover collateral” in the account.

  • If the seizure consumes the account (common on marginal positions), account.collateralBalance == 0 and the conditional check fails—no fee is paid. Value stays pooled in the contract (not stolen), but the liquidator isn’t compensated as designed.

Concrete example

  • Victim has X MYT shares; liquidation computes amountLiquidated = X and feeInYield = f (0<f<X).

  • _doLiquidation debits X (victim balance → 0), sends X-f to Transmuter, then checks if 0 >= f to pay the fee → false → fee not paid.

  • Liquidator executed the work but received no base fee even though it was included in the gross seizure.

  • Liquidations rely on external actors (searchers/keepers). If fees are frequently withheld in “full wipe” cases, the expected payout is inconsistent or negative (after gas + risk). Rational liquidators stop participating.

  • With fewer liquidations, unhealthy positions linger; vault rebalances and user withdrawals that depend on deleveraging can revert or be delayed until market conditions or buffers change.

Impact Details

  • Temporary freezing of funds for at least 1 hour. When liquidations become uneconomic, deleveraging stalls. Withdrawals/rebalances that require collateral to be freed or debt to be burned can revert, temporarily freezing user funds until incentives are fixed or conditions change.

  • Any liquidation that fully (or nearly fully) consumes a victim’s collateral can exhibit the issue.

  • Repeated occurrences reduce keeper participation across the system, compounding deleveraging delays during stress—precisely when timely liquidations are most needed.

References

  • Contract: src/AlchemistV3.sol

  • Function: _doLiquidation(...) (liquidation path where fee is gated by account.collateralBalance >= feeInYield after debiting the gross amountLiquidated): https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol#L878-L880

  • Related types: calculateLiquidation(...) (provides liquidationAmount and baseFee), convertDebtTokensToYield(...), and calls to TokenUtils.safeTransfer(...) for Transmuter and liquidator payouts. https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol#L1244-L1291

Proof of Concept

Proof of Concept

Paste the following in AlchemistV3.t.sol and run with forge test --match-test test_LiquidationBaseFee_Withheld_When_NoLeftoverCollateral:

Was this helpful?