- Lifecycle Hooks: initialize, position, swap and donate
- Hook managed fees
- swap and/or withdraw
- static or dynamic
- Swap and withdraw protocol fees
- ERC-1155 accounting of multiple tokens
- Native ETH pools like V1
- Donate liquidity to pools
Contract dependencies
This project uses Foundry to manage dependencies, compile contracts, test contracts and run a local node. See Foundry installation for instructions on how to install Foundry which includes forge
and anvil
.
git clone [email protected]:naddison36/uniswap-v4-hooks.git
cd uniswap-v4-hooks
forge install
forge update v4-periphery
The following will run the unit tests in test/CounterScript
forge test -vvv
- The CounterHook demonstrates the
beforeModifyPosition
,afterModifyPosition
,beforeSwap
andafterSwap
hooks. - The CounterScript deploys the v4 pool manager, test tokens, counter hook and test routers. It then sets up a pool, adds token liquidity and performs a swap.
- The CounterScript script deploys to a local Anvil node and does a swap.
Because v4 exceeds the bytecode limit of Ethereum and it's business licensed, we can only deploy & test hooks on a local node like Anvil.
The following runs the script/CounterScript Forge script against a local Anvil node that:
- Deploys the Uniswap v4 PoolManager
- Uses the
CounterFactory
to deploy a CounterHook contract with the correct address prefix. - Creates a new pool with
CounterHook
as the hook. - Adds token liquidity to the pool
- Performs a token swap
# start anvil with a larger code limit
anvil --code-size-limit 30000
# in a new terminal, run the Forge script
export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
forge script script/CounterScript.sol \
--rpc-url http://localhost:8545 \
--code-size-limit 30000 \
--broadcast
WARNING The above private key for account 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 is only used for Foundry testing. Do not use this known account on mainnet.
# Get the counter values from the CounterHook
export COUNTER=0x3CD91b522f2a6CB67F378d7fBee767602d5140bB
cast call $COUNTER "beforeSwapCounter()(uint256)" --rpc-url http://localhost:8545
cast call $COUNTER "afterSwapCounter()(uint256)" --rpc-url http://localhost:8545
Summary of the modify position calls
Summary of the swap calls
See here for more detailed transaction traces with call parameters and events.
- The MyHook contract has empty
beforeInitialize
,afterInitialize
,beforeModifyPosition
,afterModifyPosition
,beforeSwap
,afterSwap
,beforeDonate
andafterDonate
hooks that can be implemented. - The MyHookScript script deploys to a local Anvil node and does a swap.
# start anvil with a larger code limit
anvil --code-size-limit 30000
# in a new terminal, run the Forge script
export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
forge script script/MyHookScript.sol \
--rpc-url http://localhost:8545 \
--code-size-limit 30000 \
--broadcast
- The DynamicFeeHook contract has an empty
getFee
function that is used to set the fee for dynamic fee pools. It also has emptybeforeModifyPosition
,afterModifyPosition
,beforeSwap
andafterSwap
hooks but they are not required for a dynamic fee hook. They can be removed if not needed. - The DynamicFeeScript script deploys to a local Anvil node and does a swap. Note the fee in the PoolKey is set with the
DYNAMIC_FEE_FLAG
.
// Derive the key for the new pool
poolKey = PoolKey(
Currency.wrap(address(token0)), Currency.wrap(address(token1)), FeeLibrary.DYNAMIC_FEE_FLAG, 60, hook
);
// Create the pool in the Uniswap Pool Manager
poolManager.initialize(poolKey, SQRT_RATIO_1_1);
Summary of the swap calls
See here for more examples and details.
# start anvil with a larger code limit
anvil --code-size-limit 30000
The following runs the DynamicFeeScript against a local Anvil node
# in a new terminal, run the Forge script
export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
forge script script/DynamicFeeScript.sol \
--rpc-url http://localhost:8545 \
--code-size-limit 30000 \
--broadcast
This repository was created from this GitHub project template https://github.com/saucepoint/v4-template. Thanks @saucepoint for an excellent starting point. This repo has significantly evolved from the starting template.
- Uniswap V3 Development Book
- Uniswap v4 Core whitepaper
- Uniswap v4-core repository
- Uniswap v4-periphery repository contains advanced hook implementations that serve as a great reference.
- A curated list of Uniswap v4 hooks
- Uniswap v4 Hooks: Create a fully on-chain "take-profit" orders hook on Uniswap v4
- SharkTeam's Best Security Practices for UniswapV4 Hooks
- Research - What bad hooks look like