58358 sc high mismatched collateralweight and rawlocked causes incorrect collateral removal in sync

Submitted on Nov 1st 2025 at 15:31:29 UTC by @JoeMama for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #58358

  • Report Type: Smart Contract

  • Report severity: High

  • 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

Description

Brief/Intro

When the minimum collateralization is updated, the new ratio does not automatically rescale _totalLocked.

If a redeem happens afterwards, _collateralWeight is calculated using the _totalLocked, that reflects the previous minimum collateralization ratio. While the account.rawLocked is updated to the new minimum collateralization scale during _sync.

Because _collateralWeight and rawLocked are now on different scales, collateral decay is miscalculated, causing users to lose more or less collateral than intended depending on a increase or decrease with the new minimumCollateralization.

Vulnerability Details

During _addDebt:

_totalLocked is using the current minimumCollateralization scale

During redeem:

_collateralWeight is computed using the old _totalLocked, which does not account for any increase in minimumCollateralization

During _sync:

account.rawLocked now reflects the new minimumCollateralization, but _collateralWeight is still based on the old _totalLocked.

This mismatch causes decay to be too aggressive, users lose more collateral than intended because the collateral weight did not scale with the updated account.rawLocked.

What is needed?

The token needs to be synced after a new minimumCollateralization but before a redeem, because rawLocked is then updated. This can be done by poke, mint, deposit, or other actions that trigger _sync.

Impact Details

Users can lose too much or too little collateral during decay because _collateralWeight is calculated from the old _totalLocked while account.rawLocked uses the new minimumCollateralization scale.

https://gist.github.com/hexens-joe/c8afa5451cd5aa12db21ed3c6b517106

Proof of Concept

Proof of Concept

In the PoC there are 3 Scenario's:

Scenario 1 demonstrates the bug: too much collateral is removed.

Scenarios 2 and 3 behave correctly, removing the expected amount of collateral. They are included to show that the bug occurs when minimumCollateralization is updated after debts have already been created. Not by the minimumCollateralization itself.

In all three scenarios, the same debt (1e18) and collateral (1e18) should be removed. In Scenario 1, however, 1.2e18 collateral is removed instead

Please run the gist with forge test --mt testDecayTooMuchCollateral -vvv

output:

Was this helpful?