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 V3
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
Add this test to the end of
Alchemist.t.sol
Run the test:
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?