DynamicFeeHook on Celo

Uniswap v4 Hook Contract 0xe96b2c7416596fe707ba40379b909f42f18d7fc0 on Celo · Dynamic fee · Verified contract

Volume (24h)
$0
Value locked (TVL)
$0
All-time volume
$0
Pools using this hook
4
Swaps (24h)
0 (0 traders)
Total swaps
0

What it does

Charges a volatility-based dynamic swap fee and keeps a share of the fee spread as protocol revenue for the treasury.

How it works step by step

  • Requires pools to use a dynamic fee at initialization and registers each pool with baseFee 0.30% and maxFee 1.00%.
  • On each swap, updates an EWMA volatility from the change in sqrt price over time since the last observation.
  • Sets the swap fee to baseFee plus volatility times feeMultiplier divided by 100, capped at maxFee, and emits DynamicFeeApplied.
  • Computes the spread between the dynamic fee and baseFee and takes protocolShareBps (default 10%) of that spread from the output amount.
  • Accumulates protocol fees per currency and lets the owner sweep them to the treasury through withdrawFees.
  • Exposes view functions for current fee, volatility, pool stats and a fee estimator for a given volatility.
Swap behaviour
beforeSwap updates the pool's volatility estimate from the spot price change and sets a dynamic fee between baseFee and maxFee; afterSwap records swap volume and takes a protocol share of the spread as a hook delta.
Liquidity behaviour
No liquidity callbacks; add and remove liquidity hooks return the selector with zero delta.
Fee behaviour
Fee is computed in beforeSwap as baseFee plus volatility times feeMultiplier divided by 100, capped at the pool's maxFee, and applied via the override fee flag. Default pool config is baseFee 3000 and maxFee 10000. A protocol share (default 10%) of the spread between the dynamic fee and baseFee is taken from the output amount in afterSwap and credited to accumulatedFees.
Owner & admin controls
Owner (Ownable2Step, two-step transfer) can set volatility params (alpha max 10000, feeMultiplier unbounded), set protocol share up to 50%, change treasury, change per-pool baseFee/maxFee within MIN_FEE..MAX_FEE, withdraw all accumulatedFees to treasury, and renounce or transfer ownership. No pause and no upgrade path found.

Enabled Uniswap v4 callbacks

beforeInitialize, afterInitialize, beforeAddLiquidity, afterAddLiquidity, beforeRemoveLiquidity, afterRemoveLiquidity, beforeSwap, afterSwap

beforeInitialize validates the pool uses a dynamic fee. afterInitialize registers pool config. beforeSwap updates EWMA volatility and sets the dynamic fee override. afterSwap tracks volume and takes the protocol fee via returned hook delta. Liquidity and donate callbacks are no-ops.

Security & trust assessment

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

Who controls it: The owner can raise protocolShareBps to 50%, set feeMultiplier arbitrarily high so per-pool fees saturate at maxFee (up to 1.00%), change maxFee upward to MAX_FEE, and redirect fee withdrawals by changing treasury. The owner can also withdraw all accumulated protocol fees at any time.

Risk to user funds: The hook can take a protocol share of swap output (capped at 50% of the spread) and accumulates it in the hook contract until withdrawn. It does not hold LP principal and has no liquidity callbacks that move funds. Owner withdrawals can only drain accumulatedFees, not pool reserves.

Security findings

  • [info] Hook takes a share of swap output: afterSwap returns a positive protocolFee hook delta that the PoolManager settles against the swapper's output, so the hook takes a cut of trader output in addition to the LP fee.
  • [medium] Owner can raise swap fees without limit: setVolatilityParams has no bounds on feeMultiplier, so the owner can instantly push every pool's fee to maxFee, and setPoolConfig allows maxFee up to 1%, increasing trader costs.
  • [low] Protocol fee is taken from swap output, not from LP fees: afterSwap computes the protocol fee from delta and feeSpread but does not verify that the hook delta is funded by the pool; with a large protocolShareBps and high spread the taken amount is bounded only by the 50% cap on share, which limits but does not eliminate impact on LP returns.
  • [low] Volatility input is manipulable by spot price: beforeSwap calls poolManager.getSlot0 and volatility EWMA update on every swap, and volatility is derived from the price change over the time delta; the EWMA input is spot price and can be manipulated by a large swap in the same block, raising the fee for subsequent trades.
  • [medium] Single owner controls fee destination: withdrawFees can send native ETH or ERC20 to treasury; the owner controls the treasury address and can point it at any address, and a non-zero owner key can redirect all accrued fees.

Contract details

Verified source
Yes (DynamicFeeHook)
Compiler
solc 0.8.26+commit.8a97fa7a
Bytecode size
10,347 bytes
Upgradeable proxy
No
Detected patterns
dynamic-fee, ownable

Pools using DynamicFeeHook