57860 sc high incorrect mytsharesdeposited accounting inflates collateral and underreports bad debt enabling insolvency

Submitted on Oct 29th 2025 at 09:15:51 UTC by @algiz for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #57860

  • 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

AlchemistV3 does not reduce _mytSharesDeposited when MYT collateral is seized in liquidation, paid as fees, or force-repaid and sent to the transmuter. This means the protocol continues to report that it holds collateral (in getTotalUnderlyingValue()) that it has already transferred out.

That corrupts two critical safety mechanisms:

  1. Liquidation math, which decides whether to fully liquidate underwater debt

  2. The transmuter’s badDebtRatio, which is used to reduce redemptions when the system has bad debt.

As a result, the system can under-liquidate underwater positions (allowing bad debt to persist) and at the same time overpay claimants from the transmuter relative to true reserves. This creates a path to protocol-wide insolvency.

Vulnerability Details

The contract tracks the total MYT shares deposited across all CDPs in a global variable:

This variable is increased or decreased during deposit() or when collateral is pulled out from any CDP (withdraw(), burn(), repay(), redeem()).

However, in several flows, MYT leaves the contract but _mytSharesDeposited is not decremented. This desynchronizes accounting and causes the system to believe it has more collateral than it really does.

Those flows are: _forceRepay(), _resolveRepaymentFee(), _doLiquidation()

After any liquidation or forced repayment, the actual MYT balance of AlchemistV3 went down, but _mytSharesDeposited did not. Since _getTotalUnderlyingValue() is calculated from _mytSharesDeposited, the protocol’s own view of its TVL gets gradually inflated.

That incorrect value is used in:

  1. Alchemist's full liquidation path, when debt should be fully liquidated in high LTV global environment

  1. Calculating badDebtRatio during Transmuter's claimRedemption(), when scaling redemption amounts

Impact Details

This incorrect value has impact in multiple areas:

  1. Under-liquidation when in high TVL environment In case when the alchemistCurrentCollateralization is lower than alchemistMinimumCollateralization, the debt should be fully liquidated. However, due to inflated _mytSharesDeposited, position is only partially liquidated.

  2. Transmuter's badDebtRatio is understated and users' redemptions are not scaled down as they should Economically, this means the Transmuter may continue honouring 1:1 exits from alAssets into MYT, when it should already be scaling down. That drains what little collateral remains and accelerates insolvency. Redemptions are supposed to be throttled when the system is undercollateralized, but instead they're paid out at close to full value because the undercollateralization is being hidden. This could further prevent future users to withdraw or redeem their collateral.

References

  • https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistV3.sol#L1238-L1241

  • https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/Transmuter.sol#L219-L226

Proof of Concept

Proof of Concept

The existing testLiquidate_Undercollateralized_Position test has been extended to reflect the actual/reported totalUnderlyingValue before/after liquidations.

  1. Add the following test inside AlchemistV3.t.sol:

  1. Execute the test with

  1. Output:

Was this helpful?