56389 sc high mytsharesdeposited is not updated on liquidation outflows which could lead to solvency illusion and misreported global ratios

Submitted on Oct 15th 2025 at 11:45:24 UTC by @spongebob for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #56389

  • 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

_doLiquidation transfers amountLiquidated - feeInYield to the transmuter (and potentially feeInYield to the liquidator) without ever decrementing _mytSharesDeposited, even though those MYT shares leave the contract.

https://github.com/alchemix-finance/v3-poc/blob/b2e2aba046c36ff5e1db6f40f399e93cd2bdaad0/src/AlchemistV3.sol#L852-L865

  function _doLiquidation(uint256 accountId, uint256 collateralInUnderlying, uint256 repaidAmountInYield)
        internal
        returns (uint256 amountLiquidated, uint256 feeInYield, uint256 feeInUnderlying)
    {
        Account storage account = _accounts[accountId];

        (uint256 liquidationAmount, uint256 debtToBurn, uint256 baseFee, uint256 outsourcedFee) = calculateLiquidation(
            collateralInUnderlying,
            account.debt,
            minimumCollateralization,
            normalizeUnderlyingTokensToDebt(_getTotalUnderlyingValue()) * FIXED_POINT_SCALAR / totalDebt,
            globalMinimumCollateralization,
            liquidatorFee
        );
...

_mytSharesDeposited therefore remains inflated after every liquidation/repayment. The same omission exists in _forceRepay where collateral is sent to the transmuter while the bookkeeping variable is unchanged.

https://github.com/alchemix-finance/v3-poc/blob/b2e2aba046c36ff5e1db6f40f399e93cd2bdaad0/src/AlchemistV3.sol#L750-L763

Because _getTotalUnderlyingValue() (and thus the global collateralization ratio used inside calculateLiquidation) relies entirely on _mytSharesDeposited (https://github.com/alchemix-finance/v3-poc/blob/b2e2aba046c36ff5e1db6f40f399e93cd2bdaad0/src/AlchemistV3.sol#L1214-L1217), the protocol overstates its TVL after any such outflow.

That can mask under‑collateralization and also keeps the deposit-cap check (_mytSharesDeposited + amount <= depositCap) artificially tight even though the real balance dropped

Impact

This could lead to protocol insolvency because by overstating _mytSharesDeposited, the system believes it holds more collateral than it actually does, so global collateralization appears healthier than reality. That can keep emergency liquidations from triggering when they should, letting total debt outrun real collateral and rendering the protocol insolvent.

Recommendation

The fix is to subtract the actual amount of MYT sent out (both the repayment portion and any fee actually paid) from _mytSharesDeposited in every path that transfers tokens away.

Proof of Concept

Add this test to AlchemixV3.t.sol and run forge test --mt testPOC_MYTSharesDeposited_Accounting_Vulnerability

Logs

Was this helpful?