57460 sc high protocol fails to subtract fee from total locked when burning and repaying
Submitted on Oct 26th 2025 at 12:16:31 UTC by @securehash1 for Audit Comp | Alchemix V3
Report ID: #57460
Report Type: Smart Contract
Report severity: High
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol
Impacts:
Protocol insolvency
Description
Brief/Intro
In AlchemistV3.sol in line 482 total locked not updated when subtracting fee, The issue is that _subDebt calculates the new _totalLocked value based on the user's remaining debt, but it is unaware that some collateral was just removed to pay the fee. The _totalLocked variable represents the amount of collateral that is locked due to debt obligations. Since the fee payment reduces the user's available collateral, _totalLocked should also be reduced by the fee amount to keep the system's accounting consistent.
Vulnerability Details
The vulnerability lies within the repay and burn functions of the AlchemistV3.sol contract. Both of these functions, which allow users to reduce their debt, involve charging a protocol fee. This fee is correctly deducted from the user's collateral balance (account.collateralBalance), but not deducted from total-locked which goes to protocol receiver.
uint256 toFree = convertDebtTokensToYield(amount) * minimumCollateralization / FIXED_POINT_SCALAR;
uint256 lockedCollateral = convertDebtTokensToYield(account.debt) * minimumCollateralization / FIXED_POINT_SCALAR;
// For cases when someone above minimum LTV gets liquidated.
if (toFree > _totalLocked) {
toFree = _totalLocked;
}
// @audit :missing fee
account.debt -= amount;
totalDebt -= amount;
_totalLocked -= toFree;However, when this collateral is taken for the fee, the corresponding update to the global _totalLocked state variable is missed. _totalLocked is meant to represent the total amount of collateral that is encumbered by debt across all positions.
Later in the execution flow of both functions, a call to _subDebt is made. The _subDebt function recalculates the locked collateral for the user's position based on their new, lower debt amount. It then adjusts _totalLocked based on this recalculation. The critical flaw is that this recalculation is unaware that some collateral has already been removed to pay the protocol fee. As a result, the reduction in _totalLocked is insufficient, causing it to become progressively inflated over time as more fees are collected.
Impact Details
Incorrect solvency check on total locked which would accumulate over time
Recommended Mitigation
References
https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol?utm_source=immunefi
Proof of Concept
Proof of Concept
I added a get locked amount function Copy and paste to Alchemist.t.sol
forge test --match-path src/test/AlchemistV3.t.sol Logs:
Was this helpful?