ZoraV4CoinHook on Base

Uniswap v4 Hook Contract 0xa1ebdd5ca6470bbd67114331387f2dda7bfad040 on Base · Rewards · Verified contract

Volume (24h)
$0
Value locked (TVL)
$822
All-time volume
$1.98M
Pools using this hook
48,439
Swaps (24h)
14 (6 traders)
Total swaps
258,754

What it does

Hook for Zora V4 coin pools that mints the coin's launch liquidity curve at pool creation and, after every swap, collects LP fees, converts them to the backing currency and pays them out to the creator, referrers, the protocol and Doppler.

How it works step by step

  • On afterInitialize, checks that the pool initializer (sender) is a registered V4 coin via a version lookup contract, then builds multi-curve liquidity positions from the coin's pool configuration and mints them from the hook itself, settling through the pool manager.
  • On every afterSwap, it collects accrued fees from all hook-owned positions by calling modifyLiquidity with a zero liquidity delta.
  • Collected fees are swapped through the coin's payout swap path (possibly multi-hop through other pools) into a single payout currency, and then taken to the hook.
  • The payout is split in fixed shares: creator 50%, platform referrer 15% if set, trade referrer 15% if set (address read from hookData), Doppler 5%, and the remainder to the protocol recipient.
  • Emits Swapped (with the original msg.sender read from the router, sqrtPrice and buy/sell flag) and CoinMarketRewardsV4 events for indexing.
Swap behaviour
afterSwap reverts with NoCoinForHook if the pool was not registered. Otherwise it harvests fees from all positions, runs nested swaps via the pool manager to convert them to the payout currency, takes the proceeds and transfers them to reward recipients, then emits events. It returns a zero delta, so the swapper's own amounts are not altered. Nested swaps use full-range price limits with no slippage protection.
Liquidity behaviour
No add or remove liquidity callbacks. The hook itself is the owner of the liquidity positions: it mints them once during pool initialization via unlockCallback. Fee collection later reuses modifyLiquidity with zero delta.
Fee behaviour
The pool LP fee for the V4 multicurve configuration is 2% (LP_FEE_V4 = 20000), set by the pool configuration. The hook does not change the fee per swap. It harvests the accrued LP fees on every swap and distributes them in fixed percentages to creator, referrers, Doppler and the protocol recipient. There are no hook-level deltas taken from swappers.
Owner & admin controls
No admin controls found in the hook itself: there is no owner, pause or upgrade function, and the trusted message sender set is fixed in the constructor. However, the reward recipients, the payout swap path and the version lookup are read from the coin contract and the lookup contract, which are external and not reviewed here.

Enabled Uniswap v4 callbacks

afterInitialize, afterSwap

afterInitialize validates that the initializer is a V4 coin, stores the pool-to-coin mapping and mints the initial liquidity positions. afterSwap harvests fees, converts them to the payout currency and distributes rewards.

Security & trust assessment

Risk level: medium (verified source, high confidence).

Who controls it: The hook has no privileged key. Control rests with the coin contract and the version lookup, whose recipient addresses or swap path could redirect or block reward distribution, and could block swaps on that pool by reverting. This code does not show whether those contracts are upgradeable.

Risk to user funds: The hook briefly holds harvested fees and converted payout tokens within afterSwap and transfers them out immediately, but its code has no function to withdraw other balances. It owns the pool's LP positions, which are not user-owned. Swappers are not charged any extra amount by the hook, but swaps can be blocked if the external calls or payouts revert. Any tokens or ETH sent directly to the hook would have no rescue function.

Security findings

  • [medium] Swaps depend on external coin contract calls: afterSwap calls getPayoutSwapPath, payoutRecipient, platformReferrer, protocolRewardRecipient and dopplerFeeRecipient on the coin. If these revert, or a recipient cannot receive tokens or ETH (EthTransferFailed, SafeERC20 failure), every swap on that pool reverts.
  • [medium] Nested swaps without price limit: Fee conversion swaps use the min/max sqrt price limits and accept any output. The conversion pools can be manipulated, so harvested fees could be converted at poor prices, which affects reward recipients (not the swapper).
  • [info] Hook is the sole owner of the pool's LP positions: All initial liquidity is minted by the hook, which holds no external add or remove function. Position tick ranges are stored at initialization. Positions can only be touched through fee collection with zero liquidity delta, so principal does not appear to be withdrawable in the code shown.
  • [low] Trade referrer taken from user-supplied hookData: getTradeReferral decodes an address from hookData of the swapper, which can direct 15% of that swap's harvested fees to any address, including the swapper. abi.decode on malformed data would revert the swap.
  • [low] Trust in external lookup and router msgSender: Pool registration relies on the coinVersionLookup contract to prove the sender is a V4 coin. The trusted message sender list is only used for the event flag, and msgSender is read with try/catch, so it cannot block swaps.

Contract details

Verified source
Yes (ZoraV4CoinHook)
Compiler
solc 0.8.28+commit.7893614a
Bytecode size
14,844 bytes
Upgradeable proxy
No
Detected patterns
moves-currency, rewards, self-unlock

Pools using ZoraV4CoinHook