58291 sc medium unlike setters collateralization functions alchemistv3 initialize doesnt enforce collateralization invariants allowing to break them

Submitted on Nov 1st 2025 at 01:26:10 UTC by @hunter0xweb3 for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #58291

  • Report Type: Smart Contract

  • Report severity: Medium

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

  • Impacts:

    • Contract fails to deliver promised returns, but doesn't lose value

Description

Brief/Intro

AlchemistV3 defines multiple collateralization requirements: MinimumCollateralization, GlobalMinimumCollateralization, CollateralizationLowerBound and a relation between them:

globalMinimumCollateralization >= minimumCollateralization >= collateralizationLowerBound >= FIXED_POINT_SCALAR

This relationship is enforced in the setter functions for this variables, however AlchemistV3::initialize allows to break the invariant and start AlchemistV3 in an invariant breakage state

Vulnerability Details

AlchemistV3 defines variables for multiple collateralization requirements:

  • MinimumCollateralization,

  • GlobalMinimumCollateralization

  • CollateralizationLowerBound And also defines its setter functions

From the setter function it can be seen that the invariant enforced by AlchemistV3 is the following

However this invariant is not enforced in AlchemistV3::initialize allowing to use it to break and start contract in an non compliant state:

Impact Details

  • Collateralization requirements invariant breakage

  • AlchemistV3 is unable to perform liquidations

  • Contract failed to fullfil premises

References

https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistV3.sol#L174-L176 https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistV3.sol#L292-L312

Proof of Concept

Proof of Concept

The following PoC shows AlchemistV3::initialize() can be used to break the AlchemistV3 collateralization's invariant:

enforced by setMinimumCollateralization, setGlobalMinimumCollateralization, and setCollateralizationLowerBound AlchemistV3's functions

To do so, perform the following:

In deployCoreContracts function in src/test/AlchemistV3.t.sol modify AlchemistInitializationParams struct, only the minimumCollateralization, collateralizationLowerBound and globalMinimumCollateralization fields:

Leave the rest of struct with the original values

Create in the same file (src/test/AlchemistV3.t.sol) the following test

Exec test

Observe the AlchemistV3 invariant is bypassed

Was this helpful?