Skip to main content
Uniswap v4 hooks let you add custom logic to liquidity pools. In this guide, you will build and deploy a Counter hook on Monad Testnet, create a pool with two mock tokens, and run swaps that trigger its callbacks.

What are hooks?

Uniswap v4 stores pools in a shared contract called the PoolManager. A hook is a separate smart contract that the manager calls at selected points in a pool’s lifecycle: You choose the hook when initializing a pool. Its address is part of the PoolKey, alongside the two currencies, fee, and tick spacing. Changing the hook address creates a different pool identity; it does not update an existing pool. One hook can serve multiple pools, so pool-specific state should be keyed by PoolId. Hooks execute synchronously within the transaction. They do not run on a timer: scheduled strategies also need transactions from users or automation. See Uniswap’s hooks overview and core contracts.

Common use cases

Testnet walkthrough

The example project contains the hook, Foundry scripts, and tests. It uses contracts already deployed on Monad Testnet (chain ID 10143): Anyone can use these testnet contracts. Their addresses are in shared-infrastructure.json at the root of the example project. The PoolManager and periphery addresses differ from Uniswap’s official mainnet deployments. You deploy your own hook and two mock tokens. The mock tokens are publicly mintable and have no monetary value.

Follow the guide

Follow the pages in order, running commands from the same monad-hook directory.

Setup

Clone the pinned example and its submodules, install Node dependencies, run local tests, and prepare a testnet account.

Deploy

Deploy the Counter hook and two mock tokens.

Pool lifecycle

Initialize a pool, mint an owned PositionManager NFT, swap through Universal Router, remove liquidity, and revoke approvals.

Customize and publish

Change the hook’s behavior and prepare it for mainnet.