Overview
GeodeHook.sol is the entire Geode protocol in a single contract (~1,190 lines). It implements the Uniswap v4 IHooks interface and IUnlockCallback, intercepting swaps via beforeSwap and providing batch settlement through geodeSettleBatch().
Hook flags: BEFORE_SWAP | BEFORE_SWAP_RETURNS_DELTA
Immutables
Constants
State Variables
External Entry Points
geodeSettleBatch()
The main settlement function. Permissionless — anyone can call it and earn rewards.
- Validate pool is configured and batch interval has elapsed
- Validate all intent bindings (
poolId, deadlines) - Compute clearing price and determine fills (phase-aware: curve vs standard)
- Update batch state, emit
GeodeIntentFilledevents - Call
poolManager.unlock()→ enters flash accounting context - Inside
unlockCallback():- Pull tokens from each user via Permit2
- Route residual through AMM (standard) or bonding curve (curve mode)
- Distribute outputs pro-rata to filled intents
- Pay settler (fees + gas reimbursement)
beforeSwap()
Hook callback intercepting every swap on configured pools.
- If
sender == address(this)(hook routing residual): no fee, pass through - If pool is an Active curve pool:
_curveDirectSwap()— the hook computes the bonding curve output, charges 0.3% split three ways (reserve, treasury, surplus), and returns the full delta. The AMM processes nothing. - Otherwise (standard pool): charge
directSwapFeeBpson the swap amount — ~1/3 → treasury, ~2/3 → surplus
BEFORE_SWAP_RETURNS_DELTA:
- Takes the user’s input from the PoolManager
- Computes curve output via
ConstantProductCurveLib - Provides output to the user
- Returns a
BeforeSwapDeltathat fully satisfies the swap
geodeInitializePool()
One-time pool configuration. Curve pools (with deployer set) require the factory as caller.
registerLaunch()
Called by the factory to register permanent curve state. Sets up LaunchState with virtual reserves and token tracking.
Internal Functions
_curveDirectSwap()
Handles direct swaps on curve pools — the core of the permanent curve architecture:
- Validates exactInput only (positive
amountSpecifiedreverts) - Computes 0.3% fee, split three ways:
- Reserve fee (3334 bps) → added to
launchEthReserve/launchTokenReserve - Protocol fee (3333 bps) → sent to treasury
- Surplus fee (remainder) → accumulated in pool surplus
- Reserve fee (3334 bps) → added to
- Computes curve output from net input
- Updates
cumulativeSupplyDistributed, reserves, and token balances - Returns
BeforeSwapDeltathat fully absorbs the swap - Emits
GeodeCurveSwapevent
_computeSettlement()
Phase-aware routing:
- Active curve →
ConstantProductCurveLib.computeLaunchSettlement() - Standard →
ClearingPriceLib.computeClearingPrice()
_routeAndDistribute()
Standard mode: routes residual through poolManager.swap(), then distributes outputs.
_routeAndDistributeLaunchMode()
Curve mode: dispenses/absorbs tokens via bonding curve. Updates launchTokenReserve, launchEthReserve, and cumulativeSupplyDistributed.
_paySettler()
Pays the settler:
- Settlement fees from unrouted input deposits via
poolManager.take() - Gas reimbursement from surplus via
_fundSettlerFromSurplus()(capped atmaxGasReimbursement)
SettlerPaid with exact per-currency breakdown.
_distributeBuyOutputs() / _distributeSellOutputs()
Pro-rata distribution using each intent’s amountIn as weight. Remainder dust goes to the last filled intent.
View Functions
Events
| Event | When |
|---|---|
GeodeBatchSettled | Batch settlement completes |
GeodeIntentFilled | Each filled intent |
SettlerPaid | Settler receives payment (per-currency breakdown) |
GeodeCurveSwap | Direct bonding curve swap executed |
GeodeDirectSwap | Direct swap fee charged (standard pools) |
GeodeProtocolFeeCollected | Protocol treasury receives fee share |
GeodePoolConfigured | Pool configured for batching |
GeodeLaunched | Launch token registered |
GeodeDeployerRoyaltyPaid | Deployer royalty paid from surplus |
Source
GeodeHook.sol
View the full source code on GitHub (~1,190 lines).