StratHook on Ethereum

Uniswap v4 Hook Contract 0x2b7a5409f563a94aacc6ad75fc44cf4fcbfb18cc on Ethereum · Fee sharing · Verified contract

Volume (24h)
$526
Value locked (TVL)
$2.07K
All-time volume
$411.95K
Pools using this hook
1
Swaps (24h)
3 (1 traders)
Total swaps
2,195

What it does

Taxes 2% of every swap in the pool and routes the fee to either the wETH reserve or a STRAT burn, so the per-token floor value rises over time.

How it works step by step

  • Takes 2% of input on every swap through beforeSwap (exactInput) and afterSwap (exactOutput) using return deltas.
  • Routes wETH-denominated fees into the RESERVE and burns STRAT-denominated fees, both of which raise the floor price.
  • Maintains a 30-second lagged TWAP anchor from post-swap sqrtPrice that priceTwap() reads.
  • Lets anyone mint new STRAT at max(TWAP, spot) only when that price is at or above the floor, with proceeds going to the reserve.
  • Lets anyone call defend() to spend reserve wETH on a market buy of STRAT, clamped at the floor price, and burn the result when TWAP is below the floor.
  • Blocks LP additions in beforeAddLiquidity when the TWAP price is below the floor.
Swap behaviour
beforeSwap takes 2% of exactInput amounts and afterSwap takes 2% of realized input on exactOutput swaps. Fees are sent to the reserve when paid in wETH or burned when paid in STRAT, and the TWAP anchor is refreshed on each swap once 30 seconds have passed.
Liquidity behaviour
beforeAddLiquidity reverts when the TWAP price is below the floor (reserve per token), blocking LP additions that would dilute the floor. Removing liquidity has no hook callback.
Fee behaviour
Charges a flat 2% (200 bps) of the input amount on every swap in either direction: exactInput fees are taken in beforeSwap and exactOutput fees are taken from the realized input in afterSwap. wETH-denominated fees are sent to the reserve and STRAT-denominated fees are burned. The pool's own LP fee is untouched.
Owner & admin controls
No owner or pause functions in the ABI; the constructor fixes the wiring (WETH, STRAT, RESERVE, pool fingerprint) as immutables. defend() and mint() are permissionless. Admin power over the reserve and token lies in the external RESERVE and STRAT contracts, which are not included in the input.

Enabled Uniswap v4 callbacks

afterInitialize, beforeAddLiquidity, beforeSwap, afterSwap, beforeSwapReturnDelta, afterSwapReturnDelta

afterInitialize pins the pool to the fingerprint set at deploy; beforeAddLiquidity enforces the dilution guard; beforeSwap takes the 2% input fee on exactInput swaps; afterSwap takes the fee on exactOutput swaps and refreshes the 30-second TWAP anchor; beforeSwapReturnDelta and afterSwapReturnDelta let the hook claim those fee amounts as return deltas.

Security & trust assessment

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

Who controls it: No privileged keys are visible in this contract; the hook has no owner, pause or upgrade path. Centralization risk sits in the RESERVE and STRAT contracts it calls (approveBurnRouter, notifyAccrued, recordBurn, mint, burn), whose access control is not visible here.

Risk to user funds: The hook can take up to 2% of each swap's input through return deltas and can move reserve wETH into a market buy via defend(). It does not hold user principal beyond transient balances within a single transaction, and it cannot block swaps, though beforeAddLiquidity can block LP additions below the floor.

Security findings

  • [info] Permissionless mint and defend: defend() and mint() can be called by anyone, and mint() accepts wETH from any caller in exchange for newly minted STRAT priced at max(TWAP, spot). The price is set by the pool itself, so this is a market mechanism rather than a privileged action.
  • [medium] Price inputs depend on pool depth: priceTwap() reads a lagged anchor updated at most every 30 seconds from the post-swap sqrtPrice, and mint() uses the higher of anchor and spot. Thin liquidity could make the anchor and spot easier to push, so the floor check depends on pool depth.
  • [medium] Reserve trust dependency: The hook takes wETH from the reserve via safeTransferFrom and sends it to the PoolManager and back. The reserve must have granted approvals (approveBurnRouter) for these moves, so its code is part of the trust boundary.
  • [low] Transient custody of pool funds: The hook holds transient wETH and STRAT inside unlockCallback and returns any leftover wETH to the reserve. Failure paths between take and return could leave funds stranded on the hook until the next successful call.

Contract details

Verified source
Yes (StratHook)
Compiler
solc 0.8.26+commit.8a97fa7a
Bytecode size
15,404 bytes
Upgradeable proxy
No
Detected patterns
oracle, return-delta

Pools using StratHook