58101 sc critical repayment only liquidation overpays fee from pooled collateral
Submitted on Oct 30th 2025 at 17:00:37 UTC by @Anirruth for Audit Comp | Alchemix V3
Report ID: #58101
Report Type: Smart Contract
Report severity: Critical
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol
Impacts:
Theft of unclaimed yield
Description
Brief/Intro
When liquidation enters the “repayment-only” path (earmarks fully repay the borrower’s debt), the protocol pays the liquidator the full theoretical repayment fee even if the borrower’s collateral couldn’t fund it. The shortfall is taken from the contract’s MYT balance.
Vulnerability Details
Liquidation first earmarks and repays via _forceRepay. If this fully clears debt, it executes the following if block: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol?utm_source=immunefi#L823-L828
// If debt is fully cleared, return with only the repaid amount, no liquidation needed, caller receives repayment fee
if (account.debt == 0) {
feeInYield = _resolveRepaymentFee(accountId, repaidAmountInYield);
TokenUtils.safeTransfer(myt, msg.sender, feeInYield);
return (repaidAmountInYield, feeInYield, 0);
}The _resolveRepaymentFee computes the theoretical fee and deducts only what’s available from the borrower’s balance, but returns the full, unclamped fee: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol?utm_source=immunefi#L900-L907
The call site then transfers that full theoretical fee to the liquidator from the contract’s balance, regardless of what was actually deducted from the borrower.
The calculation in the _doLiquidation function has proper checks,
Consider the following scenario:
Debt repaid: 100 MYT; repayment fee: 10% → theoretical fee = 10 MYT.
Borrower’s remaining collateral balance: 2 MYT.
_resolveRepaymentFee deducts 2 from collateral balance but the function returns returns 10.
Liquidator receives 10 where 8 is sourced from the contract pool.
Impact Details
Direct loss of funds from the pooled collateral.
Liquidators can repeatedly extract fee shortfalls from pooled MYT across many underfunded accounts, draining the contract’s balance.
References
https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol?utm_source=immunefi#L823-L828
https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol?utm_source=immunefi#L900-L907
Proof of Concept
Proof of Concept
Paste the following test in AlchemistV3.t.sol and run forge test --match-test testRepaymentFee_Overdraw_FromPool_OnRepaymentOnlyPath
Was this helpful?