58399 sc critical precision loss in baddebtratio calculation causes overpayment and dos
Submitted on Nov 1st 2025 at 23:58:21 UTC by @gizzy for Audit Comp | Alchemix V3
Report ID: #58399
Report Type: Smart Contract
Report severity: Critical
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol
Impacts:
Protocol insolvency
Description
Summary
The badDebtRatio calculation in Transmuter.claimRedemption() suffers from insufficient precision scaling, causing the contract to overpay redemptions during bad debt scenarios. This leads to a Denial of Service (DOS) where the last withdrawer cannot exit their position because the contract attempts to transfer more MYT shares than it actually holds.
Vulnerability Details
Root Cause
In Transmuter.sol:224, the badDebtRatio is calculated as:
uint256 badDebtRatio = alchemist.totalSyntheticsIssued() * 10 ** TokenUtils.expectDecimals(alchemist.underlyingToken()) / denominator;This formula only scales by one FIXED_POINT_SCALAR (10^18), but when used in line 234 to scale down scaledTransmuted, it creates a unit mismatch:
The calculation should maintain higher precision by using two FIXED_POINT_SCALAR factors in the numerator because is a sensitive varible , i will explain how below
Mathematical Breakdown
Using real values from the POC (treating wei values as dollars for clarity):
Scenario Setup
one user
Initial Deposit: 1,000 MYT shares (worth $1,000 at initial price)
Debt Minted: $900.00000000000000090 All is sent to create redemption.
Price Crash: MYT drops 12%
Post-Crash Collateral TotalUnderlyingValue: 1,000 shares = $892.857142857142857000
Bad Debt Ratio Calculation
Current Formula:
Impact on scaledTransmuted after full year for easy vasueliztion.
When scaledTransmuted is calculated:
Current :
This looks like not much, but the impact occurs when converting to shares in redeem:
The transmuter contract requests 1,000.000000000000000259 shares but only has 1,000.000000000000000000 shares deposited. which will revert . but even of these wei is sent directly to the contract it will still revert with _mytSharesDeposited underflow becuase is greater than what we stored , so these vaule is continuosly deducted from another users funds if there's another user when redemption happens.
If protocol fee is enables this scales the amount of last user would lose.
if theres a second user that just deposited collateral with even minting debt, redeem transaction will succed but that second user wont be able to withdraw full amount due to lack of funds.
Overpayment: +259 wei shares ($0.000000000000000232 at crashed price)
Correct Formula (with proper scaling):
Just usaged of the transmuter during baddebt triggers this .
While the overpayment is only ~259 wei shares (less than $0.000001), it compounds when:
Multiple redemptions occur during bad debt
High-value positions are involved (e.g., $1M position → overpay ~$0.26) In production with realistic values:
Total collateral: $10,000,000
10 users with $1M positions each
10% price drop → bad debt state
Each redemption overpays ~$0.13 in shares
After 10 redemptions: ~$1.30 missing or more with fees → last user DOS
Impact
Denial of Service (DOS): The last user to exit their position through claimredemption cannot withdraw their collateral because the contract lacks sufficient MYT shares due to prior overpayments. Loss of User Funds: If multiple users try to claim redemptions during bad debt, the contract can become insolvent and it might preventt liquidation because of insuffient funds to transfer to transmuter.
Likelihood
High - This occurs in any scenario where:
Multiple redemptions exist when bad debt occurs
##Reference https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/Transmuter.sol#L220C9-L226C10
Proof of Concept
Proof of Concept
Add this test to src/test/AlchemistV3.t.sol (https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/test/AlchemistV3.t.sol):
Run
forge test --match-test testPOC_BadDebtRation_Precision_loss -vvvv
Was this helpful?