Reproduced Exploit
Ammplify — H-3: Pool liquidity vs node liquidity mismatch from wrong `PoolWalker.settle` route
1. WalkerLib.modify marks nodes using high index treeTick(highTick) - 1. 2. PoolWalker.settle walks high index treeTick(highTick) (one higher). 3. Settlement skips the correct right node → pool never mints that range’s position while node net records liquidity. 4. Later maker/taker/remove on the af…
Chain
Other
Category
logic
Date
Sep 2025
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: 63169-h-3-mismatch-in-actual-pools-liquidity-and-pool-nodes-liquid. Standalone Foundry PoC and full write-up: 63169-h-3-mismatch-in-actual-pools-liquidity-and-pool-nodes-liquid_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/logic/fee-calculation · wrong-state · fee-accounting
Reproduction: a self-contained Foundry PoC that compiles & runs in an isolated project with only
forge-std— no fork, no RPC, noanvil_state. Full trace: output.txt. PoC: test/63169-h-3-mismatch-in-actual-pools-liquidity-and-pool-nodes-liquid_exp.sol.
AuditVault taxonomy: severity/high · sector/dex · platform/sherlock · fee-calculation · wrong-state · variant · fee-accounting · timestamp-dependence
Key info#
| Impact | HIGH — node accounting diverges from actual pool positions; maker/taker ops on affected ranges revert |
| Protocol | Ammplify (itos-finance) |
| Vulnerable code | PoolWalker.settle uses treeTick(highTick) instead of treeTick(highTick) - 1 |
| Bug class | Off-by-one tree index → wrong settlement route |
| Finding | Sherlock 2025-09-ammplify · #63169 / issue 208 · reporter panprog (+ many) |
| Report | sherlock-audit/2025-09-ammplify-judging |
| Source | AuditVault |
| Status | Audit finding — fixed in itos-finance/Ammplify PR #14. Reproduced as a standalone local PoC. |
| Compiler | ^0.8.24 (PoC) |
TL;DR#
WalkerLib.modifymarks nodes using high indextreeTick(highTick) - 1.PoolWalker.settlewalks high indextreeTick(highTick)(one higher).- Settlement skips the correct right node → pool never mints that range’s position while node net records liquidity.
- Later maker/taker/remove on the affected range fail because the pool position is missing.
The vulnerable code#
function settle(PoolInfo memory pInfo, int24 lowTick, int24 highTick, Data memory data) internal {
uint24 low = pInfo.treeTick(lowTick);
uint24 high = pInfo.treeTick(highTick); // @> VULN: missing -1 vs WalkerLib.modify
// FIX: uint24 high = pInfo.treeTick(highTick) - 1;
Route memory route = RouteImpl.make(pInfo.treeWidth, low, high);
// ...
}
Root cause#
Asymmetric exclusive-high indexing between modify and settle. Routes diverge on the right key, so settlement can miss the dirty right leaf that modify updated.
Preconditions#
- Maker position whose
highTickmaps to a tree index wheretreeTick(high)andtreeTick(high)-1select different right keys (common on non-aligned ranges).
Attack walkthrough#
- Maker creates asset on
[-150, 150]with spacing 10. WalkerLib.modifydirties right keytreeTick(150)-1.PoolWalker.settlesettles right keytreeTick(150)instead — correct right never minted.node.net == LIQbutpool.getLiq(rightRange) == 0.- Subsequent
newMaker/newTaker/removeMakeron the affected node reverts.
Diagrams#
Impact#
Inconsistent fee/liquidity accounting; residual balances in facets; failed maker/taker/remove operations for ranges touching the mismatched node. Critical for any protocol path that trusts node state to match the underlying pool.
Sources#
- AuditVault finding #63169
- Sherlock 2025-09-ammplify judging #208
- Reduced source: sherlock-audit/2025-09-ammplify —
WalkerLib.modify/PoolWalker.settle(fix: itos-finance/Ammplify PR #14)
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 63169-h-3-mismatch-in-actual-pools-liquidity-and-pool-nodes-liquid_exp (evm-hack-registry mirror).
- AuditVault finding: 63169-h-3-mismatch-in-actual-pools-liquidity-and-pool-nodes-liquid.
Alerts & third-party analyses
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.