DeliHookConstantProduct on Base

Uniswap v4 Hook Contract 0x95afbc0fccf974b41380f24e562f15b6dd90fac8 on Base · Custom pricing · Verified contract

Volume (24h)
$0
Value locked (TVL)
$0
All-time volume
$0
Pools using this hook
29
Swaps (24h)
6 (5 traders)
Total swaps
45,334

What it does

Turns Uniswap v4 pools paired with wBLT into Uniswap-v2-style constant-product pools whose swap fees are forwarded to a FeeProcessor and which update reward gauges on every swap.

How it works step by step

  • Replaces v4 concentrated liquidity with an x*y=k curve: beforeSwap settles the whole swap against ERC-6909 claims held by the hook and returns a delta, so the core pool math is bypassed.
  • Liquidity is added and removed only through the hook's own addLiquidity and removeLiquidity, which track per-pool reserves and LP shares (v2 style, with 1000 shares locked on the first mint). Direct PoolManager liquidity calls revert.
  • Pool creation is restricted: no native ETH, wBLT must be one of the two tokens, tick spacing must be 1, the starting price must be 1:1 (sqrtPrice 2^96), and the fee must be at least 0.1%.
  • The fee, charged in wBLT, is carved out of the reserves after each swap. The hook burns its claims, takes the real tokens and sends them to the FeeProcessor, then calls feeProcessor.collectFee.
  • After every swap it pokes the DailyEpochGauge and IncentiveGauge, and on pool init it calls initPool on both. LP share changes are reported to a V2PositionHandler for reward tracking.
  • Swaps flagged by hookData 0xDE1ABEEF are treated as internal only if the sender is the FeeProcessor. This marks the FeeProcessor's buy-back swaps.
Swap behaviour
beforeSwap caches the swap parameters and computes the implicit fee. It then computes the constant-product amounts and takes and settles ERC-6909 claims to itself, returning a BeforeSwapDelta that fully replaces core pool swapping. afterSwap updates reserves net of the fee, reverts if the virtual price crosses a nonzero sqrtPriceLimit, pokes both gauges, and sends the fee tokens to the FeeProcessor.
Liquidity behaviour
Adding or removing liquidity through the PoolManager reverts with LiquidityOnlyViaHook. Users instead call the hook's addLiquidity and removeLiquidity, which run a PoolManager unlock. Tokens are moved between the user and the hook's ERC-6909 claims, v2-style pro-rata shares are minted or burned (tracked in the hook, not as tokens), and the V2PositionHandler is notified. Positions must be full range (ticks 0, 0).
Fee behaviour
The pool's static key fee (at least 0.1%) is applied as a v2-style fee inside the curve. The fee portion is always denominated in wBLT, either taken from the input or deducted from the output depending on direction. It is removed from LP reserves and forwarded to the FeeProcessor instead of staying with LPs, so LP revenue depends on whatever the FeeProcessor does downstream.
Owner & admin controls
The owner (Ownable2Step, with a two-step transfer; renounceOwnership is also available) can call setFeeProcessor, setDailyEpochGauge, setIncentiveGauge and setV2PositionHandler, each rejecting the zero address. There is no pause, no upgrade mechanism in the hook, and no fee or curve setter. The pool fee is fixed per pool key.

Enabled Uniswap v4 callbacks

beforeInitialize, afterInitialize, beforeAddLiquidity, beforeRemoveLiquidity, beforeSwap, afterSwap, beforeSwapReturnDelta

beforeInitialize validates pool parameters and marks the pool as initialized. afterInitialize registers the pool with the DailyEpochGauge and IncentiveGauge. beforeAddLiquidity and beforeRemoveLiquidity always revert so liquidity can only go through the hook. beforeSwap runs the constant-product swap and returns the delta. afterSwap updates reserves, enforces the price limit, pokes the gauges and forwards fees. beforeSwapReturnDelta lets the hook replace the swap amounts.

Security & trust assessment

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

Who controls it: The owner cannot directly take reserves or change fees. However, it can redirect the fee destination and replace the gauge and handler contracts, which are trusted in the swap and liquidity path, so it could capture all swap fees or block swaps and liquidity withdrawals through a reverting component. It can also renounce ownership, freezing the configuration.

Risk to user funds: The hook holds all LP and pool funds as ERC-6909 claims at the PoolManager, and LPs depend on its share accounting to redeem. During swaps it forwards the fee portion to the FeeProcessor. LP withdrawals call the position handler, so a faulty or malicious handler set by the owner could block them. Native ETH is unsupported.

Security findings

  • [medium] Owner can swap external components: The owner can repoint feeProcessor, dailyEpochGauge, incentiveGauge and v2PositionHandler to any address at any time. These are called during every swap and every liquidity change, so a malicious or broken replacement could revert them and block trading and withdrawals, or receive all forwarded fees.
  • [medium] Swaps and liquidity depend on external contract calls: afterSwap calls the gauges' pokePool and feeProcessor.collectFee, and _mint and _burn call the position handler. Any revert in these contracts makes swaps or add/remove liquidity revert for that pool.
  • [medium] Hook custodies all pool reserves: All liquidity is held as ERC-6909 claims owned by the hook, with accounting in its own reserve mappings. An accounting bug or an out-of-sync reserve could misprice swaps or strand funds. The code reviewed does not show any owner-driven path to withdraw reserves.
  • [info] Fees diverted from LPs to a FeeProcessor: The fee is subtracted from LP reserves and sent to the FeeProcessor on every swap, so LPs do not earn fees through reserve growth. Their yield depends on the external FeeProcessor and gauges.
  • [low] Transient swap state in contract storage: Pending fee, swap direction and internal-swap flag are stored in regular storage between beforeSwap and afterSwap and reset at the end. This is fine within a single transaction but adds gas, and a revert in between is rolled back with the transaction. The internal flag requires sender == feeProcessor, so it cannot be spoofed by others.

Contract details

Verified source
Yes (DeliHookConstantProduct)
Compiler
solc 0.8.26+commit.8a97fa7a
Bytecode size
23,943 bytes
Upgradeable proxy
No
Detected patterns
dynamic-fee, erc6909-claims, moves-currency, ownable, return-delta, rewards, self-unlock

Pools using DeliHookConstantProduct