Reproduced Exploit

Liquity — zero-ICR reinsertion strands a trove

SortedTroves removes a node and only reinserts it for a positive ICR. A zero-ICR update leaves TroveManager's existence belief inconsistent, so addCollateral and other calls revert.

Sep 2021Otherlogic3 min read

Chain

Other

Category

logic

Date

Sep 2021

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

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.

Loading fork state…

Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 18030-troves-can-be-improperly-removed-under-certain-circumstances. Standalone Foundry PoC and full write-up: 18030-liquity-zero-icr-trove-removal_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/logic/wrong-condition · vuln/logic/state-update · vuln/dos/frozen-funds

Reproduction: Fully local synthetic; run forge test and inspect output.txt. The Playground bundle replays the same 18030-liquity-zero-icr-trove-removal invariant.

Key info#

FieldValue
LossA trove remains recorded by the manager but collateral operations revert
Vulnerable contractSortedTroves (reconstructed)
Attacker EOA0x1111111111111111111111111111111111111111 (synthetic caller)
Attack contractExploit
Attack txLocal Exploit.run() call (no historical transaction)
Chain · block · dateEthereum · local stub 0x1181d03 · 2021-09
CompilerSolidity 0.8.35 (pragma ^0.8.24)
Bug classvuln/logic/wrong-condition · vuln/logic/state-update · vuln/dos/frozen-funds

TL;DR#

SortedTroves removes a node and only reinserts it for a positive ICR. A zero-ICR update leaves TroveManager's existence belief inconsistent, so addCollateral and other calls revert.

Background#

AuditVault finding 18030-liquity-zero-icr-trove-removal is an audit-time issue rather than a historical exploit. This write-up reduces the report to one state transition and keeps the claimed harm assertion executable offline.

The vulnerable code#

The minimized source is explicitly marked RECONSTRUCTED and preserves the report's blamed operation with an @> VULN marker in test/18030-liquity-zero-icr-trove-removal.sol. It is byte-identical to the Playground synthetic source. No verified production source was available in this local checkout.

Root cause#

The zero-ICR branch omits reinsertion while other protocol state still assumes the trove is in the sorted list.

Preconditions#

The affected protocol path is deployed; the attacker can reach the public operation described in the report. The synthetic removes unrelated integrations while preserving the state and authorization assumptions required for the finding.

Attack walkthrough#

  1. Open the trove, reInsert with ICR=0, and catch addCollateral reverting because contains[id] is false.
  2. The run() method requires the broken invariant and sets confirmed; the Forge trace records a passing test at output.txt:355.
  3. The remediation is to validate the accounting/state transition before accepting the external call or to consume the one-time state.

Diagrams#

flowchart TD A["Attacker invokes public path"] --> B["Vulnerable state transition"] B --> C["Inconsistent accounting or revert"] C --> D["Reported protocol harm"]

Remediation#

Validate external addresses and returned balances before updating state, and make each one-time transition explicit. Add invariant tests covering zero/deflationary/epoch-boundary inputs.

How to reproduce#

BASH
cd 18030-liquity-zero-icr-trove-removal_exp
forge test -vvv

The browser replay uses scripts/poc-configs/18030-liquity-zero-icr-trove-removal.mjs and the same local-deploy Exploit contract.

Sources#


Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • 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.