Documentation Index
Fetch the complete documentation index at: https://docs.geode.ag/llms.txt
Use this file to discover all available pages before exploring further.
Architecture Overview
Geode is a single smart contract (GeodeHook.sol, ~1,260 lines) that implements the Uniswap v4 IHooks interface. It intercepts pool activity via the beforeSwap callback and provides batch settlement through a separate entry point.
Hook flags: BEFORE_SWAP | BEFORE_SWAP_RETURNS_DELTA
The hook has four immutables set at deployment:
| Immutable | Purpose |
|---|---|
poolManager | Uniswap v4 PoolManager — the core swap and liquidity engine |
permit2 | Canonical Permit2 contract — handles gasless token pulls |
protocolTreasury | Receives 50% of direct swap fees |
factory | GeodeFactory address — authorized to register launch pools |
Two Swap Paths
Every swap on a Geode-configured pool takes one of two paths:Path 1: Direct Swap
A normal Uniswap swap that passes through the hook. ThebeforeSwap callback intercepts the swap and charges a fee (directSwapFeeBps — 0.2% for standard pools, 1% for launch pools).
The fee is split:
- 50% → protocol treasury (via
poolManager.take()) - 50% → per-pool surplus (held by the hook as ERC20 balance)
When the hook routes residual flow through the AMM during batch settlement (
sender == address(this)), no direct swap fee is charged. Only external swappers pay.Path 2: Intent Batch Settlement
The core mechanism. A permissionless settler callsgeodeSettleBatch() with arrays of signed buy and sell intents.
Settlement Flow
The complete call flow from entry to final token distribution:Step-by-Step Breakdown
Batch Validation
The settler submits arrays of buy intents, sell intents, and their Permit2 signatures. The hook checks:
- Pool is configured (
poolInitialized[poolId]) - Enough blocks have passed since last settlement (
batchInterval) - All intents target the correct pool (
poolIdbinding) - All deadlines are in the future
Anchor Price
Before computing the clearing price, the hook records the current AMM sqrtPrice as the batch-open anchor. This anchor is used later to cap residual swap slippage — preventing manipulation between batch submission and execution.
Clearing Price Computation
The clearing price equals the AMM spot price (v1 simplification). For each intent:
- Buy intent fills if its implicit limit price ≥ clearing price
- Limit price =
amountIn × Q128 / minAmountOut
- Limit price =
- Sell intent fills if its implicit limit price ≤ clearing price
- Limit price =
minAmountOut × Q128 / amountIn
- Limit price =
Fee Deduction
Settlement fees are deducted from each filled intent’s input before any routing:The fee amount stays in the PoolManager as unrouted balance for the settler to claim.
Internal Matching
The algorithm determines how much buy and sell flow can cross internally:Internally matched flow executes at the clearing price with zero AMM spread.
Residual AMM Swap
Unmatched flow routes through
poolManager.swap(). The swap uses the batch-open anchor price as a slippage limit (capped by maxResidualDeviationBps, default 5%).If the anchor price limit stops the swap early (partial fill), unconsumed input goes to the pool’s surplus.Token Distribution
Output tokens are distributed pro-rata to filled intents based on each intent’s
amountIn:- Buyers receive currency1 (from internal match + AMM output)
- Sellers receive currency0 (from internal match + AMM output)
Flash Accounting
Settlement happens inside Uniswap v4’sunlock() callback — the “flash accounting” context. During this window:
- The PoolManager tracks credits and debits for each currency
- Token pulls (via Permit2) create positive deltas
- Token distributions (via
take()) create negative deltas - AMM swaps create paired deltas
- All deltas must net to zero when
unlock()returns
Residual Price Protection
To prevent manipulation between batch submission and settlement, the hook uses a batch-open anchor price:- At the start of
geodeSettleBatch(), the current AMM sqrtPrice is recorded - When the residual routes through the AMM, the swap’s
sqrtPriceLimitX96is set to the anchor ±maxResidualDeviationBps(default 5%) - If the AMM price has moved beyond this limit (e.g., from a manipulation attempt), the swap partially fills and the unconsumed input goes to surplus
Direct Swap Fee Capture
When a non-intent user swaps through a Geode-configured pool, the hook charges a fee using paired delta accounting:poolManager.take(unspecified, hook, feeAmount)— creates a negative hook deltaBeforeSwapDelta(0, +feeAmount)— creates a positive hook delta charged to the swapper