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 thePoolManager. 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 ID10143):
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 samemonad-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.

