57969 sc insight lack of incentive to liquidate small positions can cause the system to accumulate bad debt

Submitted on Oct 29th 2025 at 17:32:00 UTC by @Oxdeadmanwalking for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #57969

  • Report Type: Smart Contract

  • Report severity: Insight

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

  • Impacts:

    • Protocol insolvency

Description

Brief/Intro

The Alchemist, allows positions to be liquidated below a minimum collateralization threshold. This liquidation is always partial, aiming to restore the position's collateralization to a targer level. Any user is allowed to open as many positions as they wish, without size constraints, with each position being identified by a unique NFT id. The lack of minimum size however, can make liquidations unprofitable for very small positions due to gas costs, especially on ETH mainnet. Since an account's positions are isolated, a malicious actor can open a large amount of small positions and in the event that they become liquidatable, the lack of incentive to liquidate can cause bad debt to the protocol.

Vulnerability Details

Upon borrowing in Alchemist, no minimum amount is enforced, only a non 0 amount and the id of the position is user supplied, with 0 indicating creation of a new isolated position of arbitrary size

    function mint(uint256 tokenId, uint256 amount, address recipient) external {
        _checkArgument(recipient != address(0));
        _checkForValidAccountId(tokenId);
@>  _checkArgument(amount > 0);
        _checkState(!loansPaused);
        _checkAccountOwnership(IAlchemistV3Position(alchemistPositionNFT).ownerOf(tokenId), msg.sender);

        // Query transmuter and earmark global debt
        _earmark();

        // Sync current user debt before more is taken
        _sync(tokenId);

        // Mint tokens to recipient
        _mint(tokenId, amount, recipient);
    }

The liquidation mechanism also does not check for a minimum size when liquidating, meaning all positions below the minimum collateralization, no matter how small can get liquidated, which is intended.

A malicious actor however can start opening a large amount of small positions denominated in MYT and wait for the positions to be liquidatable. Due to the nature of the liquidation system, the fee paid to the liquidator will not be sufficient to cover the gas costs, making liquidations unprofitable. As MYT drops in price, those liquidatable positions will accumulate until bad debt accumulates in the system, potentially causing the protocol to be insolvent.

Lastly, the protocol has no mention of a protocol owned liquidation bot that will handle those small liquidations.

Impact Details

Lack of incentive to liquidate small positions can cause the protocol to incur bad debt and potentially go insolvent. A minimum debt amount is advised per-nft position to avoid this.

References

  • https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistV3.sol#L791

  • https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistV3.sol#L418

Proof of Concept

Proof of Concept

  1. Add this test to the end of Alchemist.t.sol

  1. Run the test:

  1. The output should look like the following

We can see that for ~0,5 MYT seized, the fee was only ~0,13MYT . Assuming a price of MYT of 1.1USD due to yield accrued in the share, gas costs of 10 gwei andf ETH at 4000 USD, the total cost of liquidation given the gas measurement in the test is:

gasUsed * ETH per gas (gwei) * ETH Price = 319221 * 0.000000001 * 4000 = ~1,27 USD.

So in the end:

  • totalCost =~1,27 USD.

  • totalIncentive ~= 0,13 * 1,1 = 0,143 USD

Making small positions unprofitable to liquidate.

Was this helpful?