FreeholdHook on Ethereum
Uniswap v4 Hook Contract 0x396505179f48bd9674e2cf7ad7a991b8bc778088 on Ethereum · Custom pricing · Verified contract
- Volume (24h)
- $0
- Value locked (TVL)
- $0
- All-time volume
- $0
- Pools using this hook
- 5
- Swaps (24h)
- 0 (0 traders)
- Total swaps
- 5
What it does
Provides oracle-priced, zero-slippage swaps between sDAI and a factory-deployed synthetic fiat token by minting or redeeming the token inside the swap.
How it works step by step
- beforeSwap intercepts every swap on registered sDAI/synthetic pools and routes it through the token contract
- Buying the synthetic mints tokens from sDAI at the oracle rate minus a small mint fee
- Selling the synthetic redeems tokens back to sDAI at the oracle rate minus a redeem fee
- beforeSwapReturnDelta lets the hook fully replace the pool's pricing so the pool holds no real liquidity
- Pool registration is restricted to the creator and to tokens deployed by the immutable factory
- Accrued fees and DSR surplus are sent to a hardcoded fee recipient through permissionless flush and harvest calls
- Swap behaviour
- On each swap beforeSwap takes the input currency from the PoolManager, calls token.mint() (sDAI to synthetic) or token.redeem() (synthetic to sDAI), and settles the output back to the PoolManager. Only exact-input and exact-output swaps are routed; the pool's own curve is bypassed via the return delta.
- Liquidity behaviour
- No liquidity callbacks. The pool holds no real liquidity; liquidity is virtual and backed by sDAI held in each SyntheticFiatToken contract. effectiveLiquidity() exposes that backing.
- Fee behaviour
- The hook returns no dynamic fee override (0) so the pool's own fee field applies to the zero-liquidity pool. The actual fees are taken inside the synthetic token: mintFeeBps (max 10bp) on sDAI in, and redeemFeeBps (max 50bp, set to 30bp in the example) on sDAI out, both accrued as sDAI shares and flushable to FEE_RECIPIENT. DSR surplus is also harvestable to FEE_RECIPIENT.
- Owner & admin controls
- No owner or pause on the hook. registerPool() and rescue() are restricted to the immutable creator address, which is also the ADMIN of the factory. Token-level: harvestYield() is restricted to the immutable admin and can move surplus sDAI to feeRecipient; the token itself has no pause, owner or parameter changes. Fee recipient and fee rates are immutable.
Enabled Uniswap v4 callbacks
beforeSwap, beforeSwapReturnDelta
beforeSwap: routes each exact-input or exact-output swap into token.mint() or token.redeem() and settles the resulting tokens or sDAI with the PoolManager. beforeSwapReturnDelta: lets the hook return specified and unspecified deltas so the PoolManager accounts for the hook-handled swap instead of the pool's own curve.
Security & trust assessment
Risk level: medium (verified source, high confidence).
Who controls it: The creator key can register arbitrary pools and rescue any ERC-20 balance held by the hook to FEE_RECIPIENT. Pool registration is gated to factory-deployed tokens, so the creator cannot point the hook at a rogue token. The ADMIN can call harvestYield() on each token, but only to move DSR surplus above backing to FEE_RECIPIENT; it cannot touch user backing. No key can pause swaps or change prices.
Risk to user funds: Users' sDAI backing sits in the SyntheticFiatToken contract and is only moved by mint, redeem, flushFees and harvestYield, which cannot seize or freeze balances. The hook itself transiently holds swap funds during beforeSwap and settles them within the same transaction. Main exposure is oracle or backing-accounting risk rather than custodial control by a key.
Security findings
- [medium] Oracle dependence for pricing: The oracle rate is read from an external PriceFeedAdapter (Chainlink-based per the docs). Mint and redeem price off that rate. A 0.5% per-call deviation breaker exists, but pokeRate() can advance the accepted rate over successive calls, so a manipulated or stale oracle can still set the price used for trades.
- [low] Swap capacity bounded by sDAI backing: Swaps are fully priced by the token, not by pool liquidity. If the token's sDAI balance is insufficient, the mint or redeem call reverts, so the hook cannot fill the trade and the swap fails rather than partially filling.
- [medium] Backing accounting can desync on FX moves: Redeem caps totalBackingDai at zero when the target currency appreciated since mint, so backing accounting can drift; the shortfall is absorbed by DSR surplus. If DSR yield is insufficient, redemptions can exceed backing and the token could become under-collateralised.
- [low] Unlimited sDAI approval to registered tokens: The hook calls sdai.approve(token, max) for each registered token. A compromised or buggy SyntheticFiatToken would hold an unlimited allowance over sDAI sitting in the hook, though the hook normally holds little sDAI between swaps.
- [info] Immutable contracts with narrow admin roles: Neither the hook nor the token is upgradeable, and there are no owner-controlled pause or freeze functions; the admin and creator roles only affect fee harvest, pool registration and rescue.
Contract details
- Verified source
- Yes (FreeholdHook)
- Compiler
- solc 0.8.26+commit.8a97fa7a
- Bytecode size
- 7,260 bytes
- Upgradeable proxy
- No
- Detected patterns
- moves-currency, return-delta
Pools using FreeholdHook
- AUDF / sDAI (0.00% fee) — 24h volume $0, TVL $0, 0 swaps today
- NZDF / sDAI (0.00% fee) — 24h volume $0, TVL $0, 0 swaps today
- sDAI / EURF (0.00% fee) — 24h volume $0, TVL $0, 0 swaps today
- sDAI / JPYF (0.00% fee) — 24h volume $0, TVL $0, 0 swaps today
- GBPF / sDAI (0.00% fee) — 24h volume $0, TVL $0, 0 swaps today