57533 sc high inaccurate tvl calculation prevents liquidations leading to protocol insolvency risk

Submitted on Oct 27th 2025 at 01:20:40 UTC by @Impala53732 for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #57533

  • 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

The _mytSharesDeposited state variable, which is intended to track the total amount of yield-bearing tokens deposited by users, is not correctly updated during liquidations and other forced repayment scenarios. This leads to an inflated value for the protocol's Total Value Locked (TVL). This incorrect TVL is used to calculate the protocol's overall health (alchemistCurrentCollateralization). A falsely high collateralization ratio can prevent the liquidation of undercollateralized positions, creating bad debt and putting the entire protocol at risk of insolvency.

Vulnerability Details

The core of the issue lies in the _getTotalUnderlyingValue() function, which relies on _mytSharesDeposited to determine the total value of assets held by the Alchemist.

// filepath: /home/joe/sm-sec/v3-poc/src/AlchemistV3.sol
function _getTotalUnderlyingValue() internal view returns (uint256 totalUnderlyingValue) {
    uint256 yieldTokenTVLInUnderlying = convertYieldTokensToUnderlying(_mytSharesDeposited);
    totalUnderlyingValue = yieldTokenTVLInUnderlying;
}

Several functions that transfer yield tokens (myt) out of the contract fail to decrement _mytSharesDeposited:

  1. _doLiquidation(): When a position is liquidated, collateral is seized and transferred to the transmuter and the liquidator. The account.collateralBalance is reduced, but _mytSharesDeposited is not.

  2. _forceRepay(): This internal function, called during the liquidation process, repays debt using the account's collateral. It reduces account.collateralBalance and transfers tokens but does not update _mytSharesDeposited.

  3. _resolveRepaymentFee(): When a repayment fee is paid to a liquidator, tokens are transferred out, but again, _mytSharesDeposited is not decremented.

This discrepancy causes _mytSharesDeposited to perpetually increase or stay level, never decreasing on liquidations, even as the actual balance of myt held by the contract goes down.

Impact Details

The inflated TVL directly impacts the calculateLiquidation logic. The alchemistCurrentCollateralization is calculated in _doLiquidation and passed to this function.

If the protocol's actual health is poor but the calculated alchemistCurrentCollateralization remains above alchemistMinimumCollateralization due to the bug, the less aggressive liquidation logic is used. This can result in liquidations failing to execute (grossCollateralToSeize being 0) on positions that are genuinely undercollateralized and should be liquidated to protect the protocol. This allows bad debt to accumulate, threatening the solvency of the system.

References

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

Proof of Concept

Proof of Concept

This runnable PoC test demonstrates that AlchemistV3 fails to decrement its internal MYT-share accounting when collateral is removed during forced repayments / liquidations — causing an inflated reported TVL and an overstated protocol collateralization. The logs shows the discrepency between the MYT shares deposited and the actual MYT balance in the Alchemixv3 contract.

add the following test to Alchemixv3.t.sol and run forge test --mt test_checkPoc -vvv to view the logs

Was this helpful?