HookForge

Docs

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.