Introduction to UniSwap v4 Hooks. Creating your first UniSwap v4 hook deep dive. (long video: 52mnts) This
video provides a technical "deep dive" into developing Hooks in Uniswap
v4, focusing on creating an on-chain point system. Below is a
structured technical summary for developers, emphasizing architecture,
implementation, and security vectors.
Uniswap v4 introduces a "singleton" architecture where all pools reside
in a single contract, the PoolManager. Hooks are external smart
contracts that execute custom logic at specific points in the pool
lifecycle. To develop hooks, it is essential to use Solidity version
8.25+ and EVM Cancun for EIP-1153 support. Transient storage is a
performance pillar in v4, significantly reducing gas costs. The base
implementation generally inherits from BaseHook.sol from the
v4-periphery library to facilitate boilerplate. The
getHookPermissions() function defines which callbacks (before/after)
the hook is authorized to execute in the manager. In the video example,
the hook is also an ERC-20 to facilitate the direct issuance of points
to users. The choice to use `afterSwap` and `afterAddLiquidity` is
strategic to ensure the accuracy of the amounts transacted. In `before`
hooks, the exact amount of tokens exchanged may be uncertain due to
slippage or liquidity limits. The `BalanceDelta` parameter is crucial:
it reports the net variation of the user's tokens after the core
execution. Negative values in `BalanceDelta` indicate tokens leaving
the user's account to the pool (payment or deposit). Positive values
indicate tokens entering the user's account (receipt of a swap or
removal of liquidity). A common security/architecture error is assuming
that the `msg.sender` in the hook is the end user (EOA). In reality,
the sender in the hook is often a Router contract (e.g., Universal
Router), not the user. To identify the recipient of the points, the
video uses the `hookData` parameter to pass the user's address. The
hookData allows injecting arbitrary data (such as ZK proofs or
signatures) for validation within the hook. Pool validation is done via
PoolKey, which contains the coins, rate, tick spacing, and hook
address. v4 supports native ETH; by convention, address zero represents
ETH and will always be currency0. When implementing the hook, it is
crucial not to perform silent reverts on unsupported pools to avoid DoS
attacks. Instead of reverting, the hook should return its own function
selector to allow the transaction to proceed. The point logic in the
video allocates 20% of the ETH value spent to swaps and 100% to
liquidity provision. The security of point issuance is a critical
point: a single ERC-20 for all pools is an attack vector. An attacker
could create a pool with a fake infinite liquidity token to arbitrarily
"farm" points. The recommendation for production is to use multi-token
standards (such as ERC-6909) or separate tokens per currency pair.
Another security vector discussed is the "wash trading" or "liquidity
cycling" attack (instantaneous add/remove). Without a time lock, users
can repeatedly add and remove liquidity to inflate their points
balance. The proposed solution involves implementing a "time-lock" or
vesting mechanism for earned points. Liquidity provision should be
rewarded proportionally to the time spent in the pool (time-weighted).
The test environment uses the Deployers.sol library to simulate the
PoolManager and routers locally. Foundry is the tool of choice,
requiring specific configurations in foundry.toml for the Cancun fork.
Address mining is necessary because the hook address must encode its
permissions. The first bytes of the hook address determine which
permission flags are active for the PoolManager. The video demonstrates
the use of CurrencyLibrary to simplify manipulations and verifications
of native tokens vs. ERC-20. The use of int128 in BalanceDelta requires
careful typecasting to avoid overflows or sign errors in calculations.
The assignPoints function is an internal helper that decodes the
hookData and executes the _mint atomically. The developer must ensure
that the hookData cannot be manipulated to mint tokens at arbitrary
addresses. The v4 architecture allows "dynamic" hooks, where pool rates
can be programmatically changed by the hook. This design opens doors to
native volatility oracles or volume-based dynamic rate systems. The
technical summary emphasizes that hooks are powerful but significantly
expand the protocol's attack surface. Rigorous documentation and state
logic auditing are mandatory before mainnet deployment.