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 V3
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
_forceRepay uses the account's collateral to repay earmarked debt and can zero out account.collateralBalance.
_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.
_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).
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:
Apply the repository test testPoC_repayment_fee_drains_global_collateral added in
src/test/AlchemistV3.t.sol.This setup increases the repayment fee (50%), earmarks all of an attacker's debt, zeroes their collateral via _forceRepay, and triggers liquidation.
Run:
Logs:
Demonstrating the fee is paid from pooled collateral, not the borrower.
Was this helpful?