58547 sc high mismatched accounting and transfer for capped fees
Submitted on Nov 3rd 2025 at 07:23:58 UTC by @Petrus for Audit Comp | Alchemix V3
Report ID: #58547
Report Type: Smart Contract
Report severity: High
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
The _doLiquidation () in AlchemistV3 subtracts the full amountLiquidated from the account's collateralBalance before transferring the net amount to the transmuter and conditionally paying the feeInYield to the liquidator based on the remaining balance, typically failing the check and leaving fees unpaid or succeeding without further deduction to overstate the account's balance.
Vulnerability Details
Snippet from the affected _doLiquidation:
// update user balance and debt
account.collateralBalance = account.collateralBalance > amountLiquidated ? account.collateralBalance - amountLiquidated : 0;
_subDebt(accountId, debtToBurn);
// send liquidation amount - fee to transmuter
TokenUtils.safeTransfer(myt, transmuter, amountLiquidated - feeInYield);
// send base fee to liquidator if available
if (feeInYield > 0 && account.collateralBalance >= feeInYield) { // Post-sub check
TokenUtils.safeTransfer(myt, msg.sender, feeInYield); // No further sub!
} The function subtracts the full amountLiquidated from the account's collateralBalance before transferring amountLiquidated - feeInYield to the transmuter and checking the post-subtraction collateralBalance >= feeInYield to conditionally transfer the feeInYield to the liquidator without further subtracting it from the account balance, often preventing the fee transfer or leaving the balance overstated if transferred.
Recommendation
To fix the incorrect fee payment logic in _doLiquidation by removing the flawed post-subtraction check and always transferring the feeInYield to the liquidator (as it's intended from the liquidated collateral), while ensuring the total deduction from account.collateralBalance matches the outflows to transmuter and liquidator to maintain accurate accounting.
OR precisely, transfer amountLiquidated - feeInYield to the transmuter and feeInYield to the liquidator.
Impact Details
Liquidators are frequently underpaid or unpaid, disincentivizing liquidations, while successful transfers cause accounting mismatches that enable over-withdrawals
References
https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistV3.sol#L852
Proof of Concept
Proof of Concept
Put the test in AlchemistV3.t.sol
Run the test with: forge test --match-test testLiquidationUnpaidFeeAndUnderstatedUserCollateral -vvvv
Was this helpful?