Start here
HookForge is a catalogue of Uniswap v4 hooks for mechanisms that did not have one. There are 14 shipped: contract, tests, deploy script, manifest and documentation, all in one repository, MIT licensed.
What this is
A hook is a contract that Uniswap v4 calls at specific points in a pool's life. There are fourteen such points, and which ones a hook participates in is encoded in the low fourteen bits of the hook's own address, which is why hook addresses all end in the same few patterns and why deploying one involves mining a CREATE2 salt.
Most published hooks re-implement something that already worked. Every hook here was checked against the roughly 140 published hooks and hackathon submissions first, and each one carries its prior art and its limitation in its own NatSpec, where they end up on this site because the site is generated from the source.
Run it locally
git clone --recurse-submodules https://github.com/nirholas/hookforge
cd hookforge
# Contracts: Foundry 1.7+, Solidity 0.8.26, EVM version cancun.
cd contracts && forge build && forge test
# Packages: the SDK, the registry generator and the MCP server.
cd .. && npm install && npm test
npm run build:registry regenerates every manifest from contracts/out, so after changing a
hook's NatSpec the site and the SDK follow automatically.
Use a hook in a pool
Two calls. Fix the hook's parameters for a pool key that does not exist yet, then initialize the pool. The hook rejects a pool it was never configured for, so a misconfigured pool cannot come into existence.
// Solidity
hook.configure(key, ArbTaxDecayHook.Config({baseFee: 500, maxSurcharge: 9500, halfLife: 600}));
poolManager.initialize(key, startingSqrtPriceX96);
Note the fee-bearing hooks require the pool's fee field to be
LPFeeLibrary.DYNAMIC_FEE_FLAG. The SDK's poolKeyFor({dynamicFee: true}) sets it for you, and
the hook reverts at initialization if you forget.
The shape of a hook
Every hook extends one of two bases. ForgeFeeHook is for hooks that price each swap by overriding the LP
fee: it builds on OpenZeppelin's audited BaseOverrideFee, so the fee goes to in-range liquidity and the
hook never touches the money. ForgeHook is for everything else. Both mix in
IHookMetadata.
Per-pool parameters come through configure rather than hookData, because v4 removed
hookData from initialize. Anyone may configure a pool key whose pool does not exist yet, and
nobody may change it afterwards. A griefer who configures a key they do not intend to initialize costs the real
creator one different tickSpacing, and nothing else.
What you are trusting
These contracts are unaudited
They are written to an audited shape, built on OpenZeppelin's audited hook bases, and tested against a real
PoolManager, but no third party has reviewed them. Read the limitation section on a hook's page before
putting money behind it, and treat a deterministic address as a reservation rather than a deployment.
What you are not trusting: there are no owners, no pause switches, no upgrade paths and no privileged roles anywhere in the catalogue. A hook's parameters are fixed before its pool exists, so nobody can change the terms under liquidity that already committed to them.