← ClaudeAtlas

v4-hook-delta-accountinglisted

Detect Uniswap V4 hooks that fail to settle currency deltas with the PoolManager. Every credit/debit a hook creates (BeforeSwapDelta, afterSwap hookDelta, take/mint, donate, settle/sync) is tracked in the manager's transient nonzeroDeltaCount; if the books aren't flat when unlock returns, the whole transaction reverts (CurrencyNotSettled), and mismatched take/settle/donate either strands hook funds in the manager or lets a swap leave with unpaid debt. Activate on hooks returning deltas, calling take/settle/mint/burn/donate, or custom unlockCallback accounting.
iktok90-design/ai-smart-contract-auditor · ★ 36 · AI & Automation · score 80
Install: claude install-skill iktok90-design/ai-smart-contract-auditor
# Uniswap V4 hook delta-accounting detection ## When this applies Trigger on any of: - Callbacks returning `BeforeSwapDelta` or a non-zero `int128` `hookDelta` from `afterSwap`/`afterAddLiquidity`/`afterRemoveLiquidity` - Calls to `poolManager.take`, `settle`, `sync`, `mint`, `burn`, `donate`, `clear` - Custom `unlockCallback` that moves currency in/out of the manager - Hooks that charge custom fees, skim, or rebate by adjusting deltas - `currencyDelta` reads, or accounting that must net to zero before `unlock` returns - Donations to a pool, or take/settle pairs that should balance ## Detection patterns ### Hook takes currency but never settles (HIGH) ```solidity function afterSwap(address, PoolKey calldata key, ..., BalanceDelta, bytes calldata) external override returns (bytes4, int128) { poolManager.take(key.currency0, address(this), feeAmount); // ← creates a -debt for the hook return (this.afterSwap.selector, 0); // ← returns 0 delta, never settles } ``` `take` debits the hook's currency balance in the manager; with no matching `settle`/returned delta, `nonzeroDeltaCount != 0` and the entire `unlock` reverts `CurrencyNotSettled` — every swap on the pool reverts. **Signal:** `take`/`mint` without a balancing `settle`/`burn` or a non-zero returned `hookDelta` accounting for it. ### Returned delta not backed by a real transfer (HIGH) ```solidity return (this.afterSwap.selector, int128(feeAmount)); // claims to owe the pool feeAmo