58447 sc critical unfair collateral loss through socialized redemption costs

Submitted on Nov 2nd 2025 at 12:36:43 UTC by @MahdiKarimi for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #58447

  • Report Type: Smart Contract

  • Report severity: Critical

  • Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol

  • Impacts:

    • Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield

    • Protocol insolvency

Description

Overview

In AlchemistV3, the redemption process is designed such that the cost of redemption (collateral and protocol fees) is shared among all debt holders, while the benefit (debt reduction) is granted only to users with previously earmarked debt.

This creates an imbalance: if a user has no earmarked debt, their collateral still decays during a redemption, even though neither their debt nor earmark changes. This happens because, during the earmarking phase, earmarked debt is distributed across all existing debt holders. If a new user later joins the system by depositing collateral and minting debt, they start with zero earmarked balance. When a redemption then occurs, the collateral decay (representing redemption costs) is applied globally, causing the new user’s collateral to decrease—despite having no debt reduced or earmarked cleared.

As a result, users can lose collateral value without receiving any benefit, effectively subsidizing the redemptions of others.


Technical Description

Flawed Accounting Relationship

The issue stems from the contract’s global weight-based decay model. Two key weights control balance updates during redemptions:

Weight
Purpose
Scope

_collateralWeight

Tracks collateral and fee removal after redemptions

Global (applies to all users)

_redemptionWeight, _earmarkWeight

Track debt earmarking and redemption decay

Per-user (applies only to earmarked users)

When a redemption occurs, redeem() reduces total collateral and updates _collateralWeight based on the redeemed amount. During the next _sync(), every user’s collateral balance is scaled down using this updated weight — even if they had no earmarked debt and thus no debt relief.

Meanwhile, the actual debt reduction in _sync() depends entirely on a user’s personal earmarked balance. If a user’s earmarked == 0, their debt remains unchanged, despite their collateral being reduced through the global decay.

The outcome:

Collateral losses are socialized across all users, but the debt benefit is privatized to earmarked users.


Demonstration (PoC)

A minimal test, test_PoC_SocializedDecay_UnfairCollateralLoss() which I have included can be added toAlchemistV3.t.sol, verifies this behavior.

Scenario

  1. User A

    • Deposits 100e18 collateral

    • Mints 90e18 debt

    • 20e18 of this debt is earmarked

  2. User B (victim)

    • Deposits 100e18 collateral

    • Mints 90e18 debt

    • Has no earmarked debt

  3. Redemption phase

    • The transmuter redeems 20e18 of User A’s debt.

    • _collateralWeight increases to reflect total collateral withdrawn (principal + fee).

  4. Sync phase

    • User B calls poke(), triggering _sync()

    • His collateral balance is reduced due to global _collateralWeight, but his debt remains unchanged (since earmarked = 0).

Output Summary

User B’s debt is constant, yet they lose 10e18 collateral. That 10e18 was effectively seized to fund the redemption of User A’s earmarked debt.


Impact

This is direct loss of collateral for users

Root Cause Summary

Mechanism
Problem
Consequence

_collateralWeight (global)

Applies redemption costs to all users

Collateral loss for unrelated users

_redemptionWeight / _earmarkWeight (per-user)

Restrict debt relief to earmarked accounts

Benefit limited to selected users

_sync()

Uses global decay for collateral but per-user weights for debt

Accounting mismatch between loss and benefit


  1. During _sync(), calculate collateralToRemove as a function of each user’s personal redeemedTotal (the portion of their earmarked cleared).

  2. Apply decay locally, ensuring:

    • Users without earmarked debt do not lose collateral.

    • Debt and collateral adjustments remain symmetrical.

Proof of Concept

Proof of Concept

Was this helpful?