Reproduced Exploit
Autonomint: a Type-2 liquidated borrower can still withdraw its collateral
Chain
Other
Category
untagged
Date
Nov 2024
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 696. Standalone Foundry PoC and full write-up: 45463-h-10-users-can-withdraw-liquidated-collateral-sherlock-auton_exp in the
evm-hack-registrymirror.
Vulnerability classes: liquidation-logic · direct-drain · missing-state-update
Reproduction: deploys the REAL audited Autonomint protocol (the full
Core_logic+libset at Sherlock snapshot0d324e04d4c0ca306e1ae4d4c65f0cb9d681751b) with minimal real doubles only for the opaque external venues (Ionic lending, WETH, Synthetix, RedStone oracle) and the repo's ownEndpointV2MockLayerZero stack. No mainnet fork.
Root cause#
borrowLiquidation.liquidationType2 (used when the position is hedged with a 1x
Synthetix short instead of being covered by the CDS) omits every state change that
liquidationType1 performs. Critically it never sets depositDetail.liquidated = true
and never calls treasury.updateDepositDetails.
The withdraw path guards on exactly that flag:
// lib/BorrowLib.sol (withdraw)
if (depositDetail.liquidated) revert IBorrowing.Borrow_AlreadyLiquidated();
After a Type-1 liquidation this guard blocks the borrower. After a Type-2 liquidation
the flag is still false, so the borrower can withdraw collateral that was already
seized — the withdrawn collateral is taken from other borrowers' deposits.
Vulnerable source: src/Core_logic/borrowLiquidation.sol (liquidationType2).
Exploit walkthrough (real numbers)#
- Seed the CDS with 6,000 USDT so a borrow can be opened.
- A borrower deposits 1 ETH at $1,000 and borrows ~800 USDa.
- The admin liquidates the borrower via
LiquidationType.TWO(opens the Synthetix short).getBorrowing(...).liquidatedis asserted to still befalse. - The borrower calls
withDrawand the treasury pays 0.505 ETH of collateral to a fresh EOA — despite the position having been liquidated.
test/…_exp.sol asserts the liquidated borrower's payout balance strictly increases and
that the treasury collateral is drained.
Reproduction#
_shared/run-poc/run_poc.sh 45463-h-10-users-can-withdraw-liquidated-collateral-sherlock-auton_exp -vvvvv
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 45463-h-10-users-can-withdraw-liquidated-collateral-sherlock-auton_exp (evm-hack-registry mirror).
- AuditVault finding: 696.
- Upstream DeFiHackLabs PoC directory: src/test.
Alerts & third-party analyses
- DeFiHackLabs incident explorer: search "Autonomint: a Type-2 liquidated borrower can still withdraw its collateral".
- Web3Sec X hacked database: search.
- Rekt leaderboard: search.
- Solodit incident search: search.
These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.