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

# ClearingPriceLib.sol

> Pure library implementing the uniform clearing price algorithm for standard-mode batch auctions.

## Overview

`ClearingPriceLib` is a pure Solidity library that handles batch settlement math for **standard mode** pools — pools with an underlying Uniswap v4 AMM that has real LP liquidity. It uses the AMM's current spot price (`slot0.sqrtPriceX96`) as the uniform clearing price, determines which intents fill based on their slippage limits, calculates internal match amounts between opposing flow, and computes the residual to route through the AMM.

<Warning>
  **Standard mode only.** This library is NOT used for curve (launch mode) pools. Curve pools use `ConstantProductCurveLib.computeLaunchSettlement()` instead, where the clearing price comes from the bonding curve's spot price `(Ve + E) / (Vt - S)` and residual flow routes through the hook's reserve rather than an AMM.
</Warning>

### Two Settlement Paths

|                        | Standard Mode                            | Launch Mode (Geocurve)                 |
| ---------------------- | ---------------------------------------- | -------------------------------------- |
| **Library**            | `ClearingPriceLib`                       | `ConstantProductCurveLib`              |
| **Clearing price**     | AMM spot price from `slot0.sqrtPriceX96` | Curve spot price `(Ve + E) / (Vt - S)` |
| **Residual routes to** | Uniswap v4 AMM swap                      | Hook reserve (curve dispense/absorb)   |
| **Requires**           | Real LP liquidity in the pool            | No LP — hook IS the market maker       |

## Core Function

### `computeClearingPrice()`

```solidity theme={null}
function computeClearingPrice(
    GeodeIntent[] memory buys,
    GeodeIntent[] memory sells,
    uint256 maxBatchSize,
    uint256 ammSpotPriceQ128,
    uint256 settlementFeeBps
) internal pure returns (
    SettlementResult memory result,
    bool[] memory buyFills,
    bool[] memory sellFills
)
```

**Parameters**:

* `buys` — Buy intents, sorted by implicit limit price **descending** (most generous first)
* `sells` — Sell intents, sorted by implicit limit price **ascending** (cheapest first)
* `maxBatchSize` — Maximum allowed intents per side
* `ammSpotPriceQ128` — Current AMM spot price in Q128 fixed-point
* `settlementFeeBps` — Fee charged on each filled intent's input (in basis points)

**Returns**: `SettlementResult` with exact deposit-denominated quantities, plus boolean fill arrays.

## Algorithm

<Steps>
  <Step title="Enforce Batch Size">
    Revert if either side exceeds `maxBatchSize` (default: 128, absolute max: 256).
  </Step>

  <Step title="Verify Sort Order">
    Buy intents must be sorted by descending limit price. Sell intents must be sorted by ascending limit price. Reverts with `BuysNotSorted()` or `SellsNotSorted()` if violated.

    Sort verification uses cross-multiplication to avoid division:

    ```solidity theme={null}
    // Buys: buys[i-1].limitPrice >= buys[i].limitPrice
    buys[i-1].amountIn * buys[i].minAmountOut >= buys[i].amountIn * buys[i-1].minAmountOut
    ```
  </Step>

  <Step title="Set Clearing Price">
    The clearing price is set to the AMM's current spot price from the Uniswap v4 pool's `slot0.sqrtPriceX96`. This is a v1 simplification — the clearing price equals the pool price at the moment of settlement, rather than being computed from order book crossing.

    ```solidity theme={null}
    uint256 clearingPriceQ128 = ammSpotPriceQ128;
    ```

    This price comes from the pool's real LP liquidity. For standard pools, the AMM must have been seeded with liquidity for this price to be meaningful.
  </Step>

  <Step title="Determine Fills">
    For each intent, compute its implicit limit price and compare against the clearing price:

    ```solidity theme={null}
    // Buy fills if: amountIn/minAmountOut >= clearingPrice
    buyLimitQ128 = (buys[i].amountIn * Q128) / buys[i].minAmountOut;
    buyFills[i] = (buyLimitQ128 >= clearingPriceQ128);

    // Sell fills if: minAmountOut/amountIn <= clearingPrice
    sellLimitQ128 = (sells[i].minAmountOut * Q128) / sells[i].amountIn;
    sellFills[i] = (sellLimitQ128 <= clearingPriceQ128);
    ```

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

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

    ```solidity theme={null}
    buyFeesAmt  = (totalBuyInput  * settlementFeeBps) / BPS_DENOMINATOR;
    sellFeesAmt = (totalSellInput * settlementFeeBps) / BPS_DENOMINATOR;

    netBuyInput  = totalBuyInput  - buyFeesAmt;
    netSellInput = totalSellInput - sellFeesAmt;
    ```
  </Step>

  <Step title="Compute Internal Match">
    Convert net sell volume to buyer-side units and determine the match:

    ```solidity theme={null}
    sellVolInQuote = (netSellInput * clearingPriceQ128) / Q128;

    if (netBuyInput >= sellVolInQuote) {
        // Net buy pressure: all sellers matched
        internalMatch0 = sellVolInQuote;
        internalMatch1 = netSellInput;
        residualSwapAmount = netBuyInput - sellVolInQuote;
        residualZeroForOne = true;  // excess buys → AMM
    } else {
        // Net sell pressure: all buyers matched
        internalMatch0 = netBuyInput;
        internalMatch1 = (netBuyInput * Q128) / clearingPriceQ128;
        residualSwapAmount = netSellInput - internalMatch1;
        residualZeroForOne = false; // excess sells → AMM
    }
    ```
  </Step>
</Steps>

## Key Properties

<CardGroup cols={2}>
  <Card title="Pure Function" icon="flask">
    No state reads or writes. The entire computation is deterministic from its inputs.
  </Card>

  <Card title="Deposit-Denominated" icon="coins">
    All output quantities are in exact deposit units. No predictions about AMM output — the hook captures actual swap deltas at execution time.
  </Card>

  <Card title="Input-Side Fees" icon="receipt">
    Fees are carved from gross input before matching. Net input drives all routing decisions.
  </Card>

  <Card title="Settler Competition" icon="users">
    A malicious settler can omit intents to manipulate the clearing price. The mitigation is competition — any settler can submit a more complete batch. First valid settlement wins.
  </Card>
</CardGroup>

## Source

<Card title="ClearingPriceLib.sol" icon="github" href="https://github.com/Geode-vAMM/geodex/blob/main/contracts/src/libraries/ClearingPriceLib.sol">
  View the full source code on GitHub (\~143 lines).
</Card>
