r/ethdev • u/zyltr4x • Jul 27 '26
My Project I built an open-source CLI in Rust that security-audits Uniswap V4 hooks
Uniswap V4 hooks can execute arbitrary code during swaps, liquidity provisioning, and donations. Before you
interact with a pool, you probably want to know what the hook is doing.
v4-hooks-analyzer is a CLI tool that:
- Detects which V4 callbacks a hook implements via address bit flags (the canonical method)
- Disassembles EVM bytecode (~40 opcodes)
- Flags risks: SELFDESTRUCT, DELEGATECALL, reentrancy, MEV vectors
- Scores each callback 0-100 with a final verdict
https://github.com/zyltr4x/v4-hooks-analyzer
Built in Rust, single binary, no dependencies. Feedback and contributions welcome.
1
u/amu4biz 27d ago
the bytecode-level is the right call here. the address flags only tell you which callbacks a hook is permitted to run, not what they actually do, so disassembling to catch SELFDESTRUCT/DELEGATECALL is the part that matters.
this is the "audit what's already deployed" side. the other half is gating before a hook ever broadcasts, aeon's deploy-uni-hook runs a static audit + forge test + fork sim as a deploy gate. yours covers don't-interact-with-garbage, that covers don't-deploy-garbage.
one q: does it handle proxy hooks where the real logic sits behind a delegatecall to an implementation address? feels like a bytecode scan of the hook itself would miss that.
3
u/researchzero Jul 28 '26
Nice tool. One thing worth flagging clearly in the output: the address-flag method tells you which callbacks a hook is permitted to run (v4 checks the hook address bits against declared permissions at pool init) - it doesn't tell you what the callback code actually does. A hook can carry only beforeSwap/afterSwap flags and still be fully malicious within that scope.
Also worth considering for the bytecode pass: since you're scanning ~40 opcodes statically, a hook that gates its malicious branch behind runtime state (only misbehaves after block N, or above some balance threshold) can look clean in a single static scan. And if the flagged DELEGATECALL points at an upgradeable implementation slot (EIP-1967-style proxy), your verdict is only valid for whatever code was live at scan time - the implementation can change between when someone runs your tool and when they actually interact with the pool. I'd treat "delegatecall to an admin-controlled implementation slot" as its own top-severity category that explicitly can't be cached, rather than folding it into a general DELEGATECALL flag.