CraftingHook on Ethereum
Uniswap v4 Hook Contract 0x236b1ebcb8e8f802858b36364ff1191e1f572ecc on Ethereum · Custom pricing · Verified contract
- Volume (24h)
- $0
- Value locked (TVL)
- $0
- All-time volume
- $0
- Pools using this hook
- 1
- Swaps (24h)
- 11 (10 traders)
- Total swaps
- 11
What it does
CraftingHook seeds an ETH/ETHCRAFT pool where every swap pays a tax that starts at 85% and decays to a permanent 1% over 22 minutes, while outside LPs are blocked and the FORGE_MASTER key can withdraw all liquidity.
How it works step by step
- Holds the full LP supply of the ETHCRAFT token and seeds a single-sided ETH/ETHCRAFT v4 pool once via ignite(), callable only by FORGE_MASTER
- Blocks all external liquidity add and remove; only the hook itself can modify liquidity, via ignite() and extractLiquidity()
- Charges a tax on swaps that starts at 85% and decays linearly to 1% over 1320 seconds after ignition, then stays at 1% permanently
- Takes the tax through beforeSwap and afterSwap return deltas, minting the fee as ERC-6909 ETH credits held inside PoolManager
- Lets anyone call flushFees() to burn accrued ETH credits and send the ETH to a chosen recipient
- Lets FORGE_MASTER extract the hook's liquidity to a recipient at any time after ignition
- Swap behaviour
- Swaps are taxed only when ETH is the specified or unspecified side in the taxed direction: exact-in buys (paying ETH) and exact-out sells (receiving exact ETH) are taxed in beforeSwap, while exact-out buys and exact-in sells are taxed in afterSwap. The tax rate is currentTax(), which is 85% at launch, decays linearly to 1% over 22 minutes, then remains 1%. Buys and sells are taxed on the ETH side of the trade, so the tax falls on both directions at the same rate; the tax is not reduced for any trader.
- Liquidity behaviour
- External addLiquidity and removeLiquidity calls revert with ExternalLiquidityBlocked because beforeAddLiquidity and beforeRemoveLiquidity require sender to be the hook. Liquidity is only added once during ignite() (single-sided ETHCRAFT over the range FORGE_TICK to IGNITION_TICK) and removed through extractLiquidity() by FORGE_MASTER. afterAddLiquidity returns a zero delta and does nothing else.
- Fee behaviour
- The pool's static fee is 0; the hook applies its own time-decaying tax via return deltas, starting at 85% and falling to 1% over 1320 seconds after ignition, then fixed at 1%. Collected fees are minted to the hook as ERC-6909 ETH credits, readable through collectedFees() and withdrawable with flushFees().
- Owner & admin controls
- FORGE_MASTER, an immutable address set in the constructor, is the only account that can call ignite(), which can be run only once, and extractLiquidity(), which can withdraw any amount of the hook's liquidity to any non-zero recipient at any time after ignition. No owner, pause, upgrade or parameter-change functions are present in the decoded ABI, and the tax parameters are constants. Anyone can call flushFees(), but it only sends accrued fees to the recipient they specify.
Enabled Uniswap v4 callbacks
beforeInitialize, beforeAddLiquidity, afterAddLiquidity, beforeRemoveLiquidity, beforeSwap, afterSwap, beforeSwapReturnDelta, afterSwapReturnDelta
beforeInitialize restricts the pool to ETH as currency0, fee 0 and tick spacing 200. beforeAddLiquidity and beforeRemoveLiquidity block all liquidity changes except those initiated by the hook itself. afterAddLiquidity is a no-op returning a zero delta. beforeSwap and afterSwap take the tax as ETH via return deltas. beforeSwapReturnDelta and afterSwapReturnDelta are enabled because the hook returns non-zero deltas in swap callbacks.
Security & trust assessment
Risk level: medium (verified source, high confidence).
Who controls it: FORGE_MASTER controls launch via ignite() and can withdraw all liquidity via extractLiquidity() at any time, which would strand traders and LPs even though the tax and gating logic cannot be changed.
Risk to user funds: The hook holds the full ETHCRAFT LP supply and the pool's ETH liquidity, and it holds minted ETH fee credits in PoolManager. FORGE_MASTER can move all of the liquidity to any address, while anyone can trigger flushFees() but only to a recipient they choose, and the hook cannot move user wallet funds directly.
Security findings
- [high] FORGE_MASTER can drain all liquidity at will: extractLiquidity(uint128,address) lets FORGE_MASTER remove any amount of the hook-held liquidity to an arbitrary recipient with no timelock or cap, which removes the pool's depth from traders and LPs.
- [medium] Tax is taken on the ETH side of every trade: Both buys and sells are taxed at currentTax(), starting at 85% during the first 22 minutes, which can make the effective price much worse for traders during that period.
- [info] External liquidity is blocked: beforeAddLiquidity and beforeRemoveLiquidity revert with ExternalLiquidityBlocked for any sender other than the hook, so ordinary LPs cannot enter or exit the pool.
- [info] Hook mints fee credits held in PoolManager: Taxes are minted as ERC-6909 ETH claims to the hook and are only released by flushFees(), so the hook holds ETH value inside PoolManager until anyone calls flushFees().
- [info] Immutable, non-upgradeable design: The contract is not a proxy and exposes no upgrade or pause function, and its tax constants are compile-time values.
Contract details
- Verified source
- Yes (CraftingHook)
- Compiler
- solc 0.8.26+commit.8a97fa7a
- Bytecode size
- 14,160 bytes
- Upgradeable proxy
- No
- Detected patterns
- erc20, erc6909-claims, moves-currency, return-delta, self-unlock, tax