> ## 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.

# How It Works

> Settlement flow, clearing price algorithm, and Uniswap v4 hook architecture.

## Architecture Overview

Geode is a single smart contract (`GeodeHook.sol`, \~1,190 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 \~1/3 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 swap that passes through the hook's `beforeSwap` callback. Behavior depends on pool type:

**Curve pools** (launched tokens): The hook computes the bonding curve output and returns the full delta via `BEFORE_SWAP_RETURNS_DELTA`. The v4 pool has no liquidity — the hook IS the market maker. A 0.3% fee is split three ways:

* **\~1/3** → curve ETH reserve (permanently increases the floor price)
* **\~1/3** → protocol treasury
* **\~1/3** → per-pool surplus (funds settler gas reimbursement)

**Standard pools** (existing AMM liquidity): The hook charges a fee on the unspecified (output) side of the swap:

* **\~1/3** → protocol treasury (via `poolManager.take()`)
* **\~2/3** → per-pool surplus (held by the hook as ERC20 balance)

<Info>
  **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.
</Info>

### Path 2: Intent Batch Settlement

The core mechanism. A permissionless settler calls `geodeSettleBatch()` with arrays of signed buy and sell intents.

## Settlement Flow

The complete call flow from entry to final token distribution:

```
geodeSettleBatch(key, buys[], sells[], buySigs[], sellSigs[])
  │
  ├─ Validate batch interval (≥ 1 block since last settlement)
  ├─ Validate intent bindings (poolId, deadlines)
  ├─ Compute clearing price + fills
  │   ├─ Curve mode → ConstantProductCurveLib.computeLaunchSettlement()
  │   └─ Standard mode → ClearingPriceLib.computeClearingPrice()
  │
  ├─ Update batch state, emit GeodeIntentFilled events
  │
  └─ poolManager.unlock(callbackData)
      └─ unlockCallback()
          └─ _settlementUnlockCallback()
              │
              ├─ Pull tokens from each user via Permit2
              │   └─ permitWitnessTransferFrom(owner → poolManager)
              │
              ├─ Route and distribute
              │   ├─ Standard: AMM swap for residual
              │   ├─ Curve: dispense/absorb via bonding curve
              │   ├─ Distribute currency1 to buyers (pro-rata by amountIn)
              │   └─ Distribute currency0 to sellers (pro-rata by amountIn)
              │
              └─ Pay settler
                  ├─ Settlement fees (from unrouted input deposits)
                  └─ Gas reimbursement (from surplus, capped)
```

### Step-by-Step Breakdown

<Steps>
  <Step title="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 (`poolId` binding)
    * All deadlines are in the future
  </Step>

  <Step title="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`
    * **Sell intent fills** if its implicit limit price ≤ clearing price
      * Limit price = `minAmountOut × Q128 / amountIn`

    Intents that don't meet the clearing price are skipped — they keep their tokens.
  </Step>

  <Step title="Fee Deduction">
    Settlement fees are deducted from each filled intent's input **before** any routing:

    ```
    grossInput = intent.amountIn
    fee = grossInput × settlementFeeBps / 10,000
    netInput = grossInput - fee
    ```

    The fee amount stays in the PoolManager as unrouted balance for the settler to claim.
  </Step>

  <Step title="Internal Matching">
    The algorithm determines how much buy and sell flow can cross internally:

    ```
    sellVolumeInQuote = netSellInput × clearingPrice / Q128

    if netBuyInput ≥ sellVolumeInQuote:
        internalMatch = sellVolumeInQuote (all sellers matched)
        residual = netBuyInput - sellVolumeInQuote (excess buys → AMM/curve)
    else:
        internalMatch = netBuyInput (all buyers matched)
        residual = netSellInput - matchedSells (excess sells → AMM/curve)
    ```

    Internally matched flow executes at the clearing price with zero AMM spread.
  </Step>

  <Step title="Residual Routing">
    Unmatched flow routes through the appropriate venue:

    * **Standard pools**: `poolManager.swap()` against the AMM
    * **Curve pools**: Dispense/absorb via the bonding curve (tokens from/to hook reserve)
  </Step>

  <Step title="Token Distribution">
    Output tokens are distributed pro-rata to filled intents based on each intent's `amountIn`:

    * **Buyers** receive currency1 (from internal match + residual output)
    * **Sellers** receive currency0 (from internal match + residual output)

    Distribution uses remainder-to-last for dust rounding.
  </Step>

  <Step title="Settler Payment">
    The settler receives:

    1. **Settlement fees** in both currencies (from the unrouted input deposits)
    2. **Gas reimbursement** drawn from surplus (capped at `maxGasReimbursement`, default 0.01 ETH)

    A `SettlerPaid` event emits the exact per-currency breakdown for on-chain auditing.
  </Step>
</Steps>

## Flash Accounting

Settlement happens inside Uniswap v4's `unlock()` 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

If they don't, the entire transaction reverts. This is Uniswap v4's core safety guarantee — nothing can be created or destroyed, only moved.

## Direct Curve Swap Mechanics

For curve pools, `beforeSwap` handles the entire swap through the bonding curve:

1. The hook computes the curve output using `ConstantProductCurveLib.tokensForEth()` (buy) or `ethReturnOnSell()` (sell)
2. A 0.3% fee is deducted from the input and split three ways (reserve, treasury, surplus)
3. For buys: ETH goes to `launchEthReserve`, tokens are dispensed from `launchTokenReserve`
4. For sells: Tokens are absorbed back, ETH is returned from reserve
5. The hook returns the full delta via `BeforeSwapDelta`, so the AMM processes nothing

The reserve fee portion permanently increases the curve's floor price — every direct swap ratchets the minimum value upward.

## Direct Swap Fee Capture (Standard Pools)

When a non-intent user swaps through a standard Geode-configured pool, the hook charges a fee using paired delta accounting:

1. `poolManager.take(unspecified, hook, feeAmount)` — creates a negative hook delta
2. `BeforeSwapDelta(0, +feeAmount)` — creates a positive hook delta charged to the swapper

The two net to zero for the hook. The swapper pays the fee as reduced output. \~1/3 goes to the protocol treasury; \~2/3 accumulates as surplus for settler gas reimbursement.

<Note>
  **Read next**: [Intents](/intents) for the signing and Permit2 integration, or [Economics](/economics) for the full fee model.
</Note>
