56622 sc critical repayment fee overpays liquidators using pooled collateral after forcerepay

Submitted on Oct 18th 2025 at 14:32:26 UTC by @vivekd for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #56622

  • Report Type: Smart Contract

  • Report severity: Critical

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

  • Impacts:

    • Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield

Description

Brief/Intro

During liquidation, _resolveRepaymentFee returns a fee based on the earmarked debt repaid. If the borrower has no collateral left—common after _forceRepay—the function still returns the full fee even though nothing was deducted from the borrower. _doLiquidation then pays that fee out of the Alchemist's global MYT balance, siphoning other users' collateral to the liquidator.

Vulnerability Details

  1. _forceRepay uses the account's collateral to repay earmarked debt and can zero out account.collateralBalance.

  2. _resolveRepaymentFee computes fee = repaidAmountInYield * repaymentFee / BPS and only reduces the borrower's balance by min(fee, account.collateralBalance). When the balance is zero, it subtracts nothing but still returns the full fee.

  3. _liquidate calls _resolveRepaymentFee, receives the inflated feeInYield, and transfers that amount to the liquidator: TokenUtils.safeTransfer(myt, msg.sender, feeInYield). Since the borrower contributed nothing, the transfer comes directly from the Alchemist's pooled MYT (i.e., other users' collateral).

  4. The PoC (testPoC_repayment_fee_drains_global_collateral in src/test/AlchemistV3.t.sol) shows a liquidation where the liquidator collects a fee from pooled funds rather than the borrower's own shares.

Impact Details

  • A malicious liquidator can repeatedly target accounts whose collateral was consumed by _forceRepay. Each liquidation yields a positive fee paid from pooled funds, enabling unlimited extraction.

  • Every exploit reduces the Alchemist's collateralization, threatening solvency and allowing the attacker to drain the MYT pool even though borrowers cannot repay.

  • All Alchemist depositors are affected: their backing collateral is transferred to the attacker through liquidation fees they should never have owed.

Proof of Concept

Proof of Concept

code:

  1. Apply the repository test testPoC_repayment_fee_drains_global_collateral added in src/test/AlchemistV3.t.sol.

  2. This setup increases the repayment fee (50%), earmarks all of an attacker's debt, zeroes their collateral via _forceRepay, and triggers liquidation.

  3. Run:

  1. Logs:

Demonstrating the fee is paid from pooled collateral, not the borrower.

Was this helpful?