58769 sc high forcerepay fails to decrement global cumulativeearmarked causing redemption accounting desynchronization and potential protocol wide redemption halt

Submitted on Nov 4th 2025 at 12:43:00 UTC by @Pataroff for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #58769

  • Report Type: Smart Contract

  • Report severity: High

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

  • Impacts:

    • Smart contract unable to operate due to lack of token funds

Description

Brief/Intro

The cumulativeEarmarked variable, which tracks protocol-wide earmarked debt for redemptions, is properly decremented during normal repay() calls. However, during liquidations, which calls _forceRepay(), the same reduction is not applied. As a result, cumulativeEarmarked remains overstated even though the underlying debt and collateral have been settled.

Vulnerability Details

When a user repays debt normally using repay(), the protocol decreases both the user’s earmarked amount and the global cumulativeEarmarked:

function repay(uint256 amount, uint256 recipientTokenId) public returns (uint256) {
    ...
    // Repay debt from earmarked amount of debt first
    uint256 earmarkToRemove = credit > account.earmarked ? account.earmarked : credit;
@>  account.earmarked -= earmarkToRemove;

    uint256 earmarkPaidGlobal = cumulativeEarmarked > earmarkToRemove ? earmarkToRemove : cumulativeEarmarked;
@>  cumulativeEarmarked -= earmarkPaidGlobal;
    ...
}

However, during liquidations (alchemist.liquidate()), the protocol internally calls _forceRepay(). This function correctly updates the user’s local account.earmarked but never decreases the global cumulativeEarmarked value. This creates a permanent mismatch between real earmarked debt and what the protocol believes is earmarked.

Impact Details

References

AlchemistV3.sol#L498-L546arrow-up-right

AlchemistV3.sol#L738-L782arrow-up-right

Proof of Concept

Proof of Concept

Was this helpful?