58177 sc high transmuter claimredemption cant update mytsharesdeposited leading to permanent underlying value state inside alchemist
Submitted on Oct 31st 2025 at 06:34:16 UTC by @farismaulana for Audit Comp | Alchemix V3
Report ID: #58177
Report Type: Smart Contract
Report severity: High
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/Transmuter.sol
Impacts:
Protocol insolvency
Description
Brief/Intro
the function Transmuter::claimRedemption only update _mytSharesDeposited if it invokes AlchemistV3 redeem function. but the problem is the MYT that is already inside the Transmuter contract beforehand that also get sent into the user claiming the redemption would not deducting the MYT share state. Effectively this would inflate the underlying value state that is used by various function, which in return would be inaccurate.
Vulnerability Details
it is important to understand that, the MYT sent into Transmuter contract because liquidation SHOULD be still counted toward _mytSharesDeposited which translate into whole AlchemistV3::getTotalUnderlyingValue this is an intended behavior.
that’s why when we check _doLiquidation when the user collateral is sent to Transmuter, there are no reduction in _mytSharesDeposited . because this still count toward protocol underlying value. this SHOULD only reduced when the MYT is sent out from Transmuter contract as part of claim redemption and when the alAsset redeemed is burned.
the issue lies in the Transmuter::claimRedemption , because this is when the MYT is transferred out from the protocol. When matured MYT would get sent into the user, it would invoke redeem function if the balance of Transmuter is not enough. However, the current Transmuter balance that is get sent other than via redeem would not reduced the _mytSharesDeposited.
Ultimately, the protocol would left with inflated _mytSharesDeposited even if the MYT already get sent out to user for redemption.
the snippet of claimRedemption above is calculating how much should be sent into msg.sender. the claimYield contains two type of MYT token: 1) the just redeemed from AlchemistV3::redeem function and, 2) the holding balance of MYT token via liquidation and in some cases repayment.
there are no _mytSharesDeposited update as we can see inside the claimRedemption function itself.
worth to note that while repay flow also sent MYT into transmuter, it is not necessary to reduce the MYT shares because the original collateral inside AlchemistV3 still belong to the borrower who just repaid their debt. they can withdraw it if they want. so it is safe to say that this claim redemption issue would occur only from MYT that is gent sent to transmuter because of liquidation.
Impact Details
the core issue is that the
_mytSharesDepositedvariable becomes artificially inflated. this single bad value cascades, causing the protocol to miscalculate its true health factor.Transmuterrelies on this inflated value to check for bad debt. When the market price of MYT drops, the Transmuter will fail to detect the problem and will not see that the AlchemistV3 is undercollateralized.because the
Transmuteris blind to the bad debt, it will continue to process redemption claims at a 1:1 ratio. This allows users to redeem assets at full value, effectively draining the protocol of its remaining healthy collateral.this inflated value also breaks other critical functions like liquidation and deposit caps
most severe impact is protocol insolvency. the combination of failing to detect bad debt, allowing unsafe redemptions, and failing to liquidate bad positions will drain the protocol of all its value, leading to a complete loss for users.
References
https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/Transmuter.sol#L250-L266
Proof of Concept
Proof of Concept
add this to src/test/AlchemistV3.t.sol
the test would pass, showing that the alchemist underlying value is constant before the liquidation happen, after liquidation happen and after the redemption where the MYT is getting out of protocol.
Was this helpful?