StableStableHook on Ethereum
Uniswap v4 Hook Contract 0x4509b7eb3f9641226804fea4976963435d1c6080 on Ethereum · Dynamic fee · Verified contract
- Volume (24h)
- $0
- Value locked (TVL)
- $0
- All-time volume
- $120.87M
- Pools using this hook
- 1
- Swaps (24h)
- 0 (0 traders)
- Total swaps
- 38,084
What it does
A dynamic fee hook for stable-stable pools that charges a fee only when the price drifts from a reference price outside an optimal range, with the fee decaying over time toward a target.
How it works step by step
- Restricts pool initialization to the owner via initializePool, requiring a dynamic fee and this hook address
- Reverts any external attempt to initialize a pool using this hook
- Computes a per-swap LP fee from the ratio of AMM price to a reference sqrt price
- Keeps a fixed optimal range around the reference price where the fee keeps pre-impact price at the boundary
- Decays the fee exponentially toward a target fee outside the optimal range, based on blocks elapsed
- Lets a configManager update each pool's fee configuration (k, logK, optimal fee, target multiplier, reference price) with validation
- Swap behaviour
- Each swap computes a dynamic LP fee from the pool price relative to a reference price, with zero fee for swaps that move price back toward reference and a decaying fee for swaps that move it further away, and returns it with the override flag; no balance delta is taken.
- Liquidity behaviour
- No liquidity callbacks.
- Fee behaviour
- Dynamic LP fee returned per swap via OVERRIDE_FEE_FLAG. Inside an optimal price range around a reference sqrt price the fee is set so pre-impact prices stay at the range boundary; outside the range, the fee decays exponentially toward a target fee (derived from far boundary minus close boundary scaled by targetMultiplier) based on blocks elapsed, and only the direction moving away from reference is charged. Fee is capped by validation of optimalFeeE6 <= 1e4 (1%) for the optimal range parameter.
- Owner & admin controls
- Owner (Ownable) can call initializePool and renounceOwnership or transferOwnership. A configManager address (set at deployment, changeable only by the current configManager via setConfigManager) can call updateFeeConfig to change per-pool k, logK, optimalFeeE6 (capped at 1%), targetMultiplier and referenceSqrtPriceX96, subject to validation; setting configManager to address(0) freezes fee config. No pause or upgrade mechanism found.
Enabled Uniswap v4 callbacks
beforeInitialize, beforeSwap
beforeInitialize reverts for any sender other than the hook flow, so pools can only be initialized through initializePool which enforces a dynamic fee and this hook address. beforeSwap computes and returns the dynamic fee override for each swap.
Security & trust assessment
Risk level: medium (verified source, high confidence).
Who controls it: The owner controls which pools get initialized with this hook, and the configManager can change fee parameters (decay constant, optimal range width, target multiplier and reference price) for any pool at any time, which directly changes the fee users pay on swaps. The configManager can set a fee range that is valid but economically unfavourable to traders or LPs, and reference price changes can shift which swaps are charged.
Risk to user funds: The hook does not take or hold user tokens and does not use return deltas, so it cannot directly seize funds. Users are exposed to the fee level set by the configManager, which can be changed for live pools, and a bug in the decay or boundary math could cause unexpected fees, which the source's comments indicate may revert on out-of-range prices.
Security findings
- [medium] Privileged fee parameter control: The configManager can call updateFeeConfig at any time to change the reference sqrt price, k, optimal fee and target multiplier of a live pool, changing swap fees immediately without a timelock.
- [low] Bounded but mutable fee parameters: Validation caps optimalFeeE6 at 1% and checks k/logK consistency and price bounds, which limits the extreme values a configManager can set, but fee levels within these bounds can still be changed.
- [info] Owner and configManager roles are separate: The owner can transfer ownership or renounce it; ownership controls only pool initialization, not fee updates. The configManager can be set to address(0) to permanently freeze fee configuration.
- [info] No direct fund custody: The hook does not use beforeSwapReturnDelta or any return delta, and does not hold or move user funds beyond normal pool accounting; fees are applied through the LP fee override only.
- [info] Start-of-block price caching: Fee state is cached per block; the start-of-block sqrt price is used for fee calculation in subsequent swaps of the same block, which the source documents as a deliberate trade-off against swap splitting.
Contract details
- Verified source
- Yes (StableStableHook)
- Compiler
- solc 0.8.26+commit.8a97fa7a
- Bytecode size
- 11,277 bytes
- Upgradeable proxy
- No
- Detected patterns
- dynamic-fee, ownable
Pools using StableStableHook
- USDC / USDT (Dynamic fee) — 24h volume $0, TVL $0, 0 swaps today