> ## Documentation Index
> Fetch the complete documentation index at: https://continuum-ec12e897.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Listing a market

> How a new asset becomes a Continuum market - the operator flow, end to end.

Listing a new market is an operator action today (admin authority on the protocol). Once governance is wired, listings will route through CNTM votes.

This page describes the operational flow at a level you can use to:

1. Anticipate when a market is about to launch.
2. Replicate the flow in a private deployment (forks, testnet integrations).
3. Understand which addresses get derived where.

## Decision: pick the asset

Continuum's targeted launch is **TradFi only** - equities, indices, commodities, FX. No crypto.

Asset checklist:

* [ ] Has a reliable Pyth on-chain feed (preferred) or Hermes feed (fallback).
* [ ] Volatility regime is defined enough to pick a book geometry and spread floor (index vs liquid equity vs volatile equity).
* [ ] Initial price (`initial_l_price`) chosen - this anchors the constant product. Pick something close to the current spot.
* [ ] OI cap chosen - typically 2× expected initial pool depth.

## Sequence

The reference scripts live in [`scripts/`](https://github.com/continuum-markets/continuum/tree/main/scripts) of the protocol repo. Operators run them in order:

<Steps>
  <Step title="Create the market">
    ```
    SYMBOL=NVDA INITIAL_PRICE=120 bun run scripts/create-synthetic-market.ts
    ```

    Creates the `Market` PDA, allocates L and S SPL mints (mint authority = market PDA), creates the collateral vault. Sets `keeper_authority` and `fee_recipient`.
  </Step>

  <Step title="Initialize the per-market CLP">
    ```
    SYMBOL=NVDA bun run scripts/initialize-clp.ts
    ```

    Creates the per-market `Clp` PDA + per-market vault (cUSDC token account).
  </Step>

  <Step title="Set OI cap">
    ```
    SYMBOL=NVDA OI_CAP=250000 bun run scripts/update-clp-oi-cap.ts
    ```

    OI cap in cUSDC (lamports). Tighter is safer.
  </Step>

  <Step title="Create CLP token ATAs">
    ```
    SYMBOL=NVDA bun run scripts/create-clp-token-atas.ts
    ```

    The CLP PDA needs ATAs for L, S, and cUSDC so it can hold inventory for the books and committed-order provisioning.
  </Step>

  <Step title="Bootstrap the native books">
    Two pools per market - one per side - created, configured, seeded, and enabled in one idempotent script:

    ```
    MARKETS=NVDA bun run scripts/init-clmm-pools.ts
    ```

    Per pool it runs `init_pool` (PDA seeds `[b"pool", market, side]`), creates the pool vaults, sets the 2-zone geometry (`configure_pool_geom`), seeds inventory (one paired mint funds both sides' asks; cUSDC funds the bids), and posts the first `set_pool_shape` - which enables the pool. Geometry per vol class:

    | Asset class                    | Core step | Core bins | Wings      | Spread floor (`min_bps`)     |
    | ------------------------------ | --------- | --------- | ---------- | ---------------------------- |
    | Index ETF (QQQ, SPY)           | 15-20bps  | 3         | 250-300bps | 15-18bps                     |
    | Volatility / high-vol (VXX)    | 40bps     | 2         | 600bps     | 40bps                        |
    | High-growth single name (NVDA) | 40bps     | 2         | 600bps     | \~2x the asset's 5-min sigma |

    The rule of thumb is empirical: the static floor should start at roughly **2x the asset's 5-minute volatility** - the keeper's slow auto-floor self-corrects it from live data within days, so err high. No model training is required for any listing: the spread engine runs on the realized ratchet and floors alone.
  </Step>

  <Step title="Set per-market config">
    Add the market's `min_bps`, `floor_mult`, and (for high-vol single names) `fee_mult` to the keeper's per-market config. `fee_mult` enables vol-informed mint/redeem fees - the paired-arb hurdle scales with volatility exactly when the moves that clear it get big.
  </Step>

  <Step title="Fund global vault (if not already)">
    ```
    AMOUNT=200000 bun run scripts/admin-fund-global-vault.ts   # devnet (cranks faucet)
    AMOUNT=200000 bun run scripts/admin-fund.ts                # mainnet (admin holds USDC)
    ```
  </Step>

  <Step title="Wait for keeper">
    The keeper picks the new pools up on its next book-manager cycle (30s): it re-pins them to NAV with the vol-scaled shape and takes over inventory management (refill / trim / bid cap). The market is live as soon as the bootstrap script finishes.
  </Step>

  <Step title="Verify">
    ```
    bun run scripts/protocol-status.ts
    ```

    Should show the new market with `OI utilization`, `pool depth`, `seeded amount`. The frontend automatically picks up new markets from the registry.
  </Step>
</Steps>

## Geometry and spread guidance

The books don't charge a swap fee - the half-spread (empty inner bins around NAV) is the price of immediacy. Trade-offs when choosing the core step and `min_bps`:

| Tighter (core 15bps, low floor)         | Wider (core 40bps, high floor) |
| --------------------------------------- | ------------------------------ |
| Better instant-trade pricing            | Worse instant-trade pricing    |
| More exposure to toxic flow during gaps | Loss per gap capped lower      |
| Suits low-vol broad indices             | Suits high-vol or single names |

Err wide at listing: the slow auto-floor tightens a too-conservative floor within days, but a too-tight floor donates depth to arbitrage from minute one. The reposition gate should sit just below the market's paired-arb hurdle (first funded bin + 10bps fee), which is also where the backtested optimum lands.

## What happens once a market is live

| Time after listing | Event                                                                                            |
| ------------------ | ------------------------------------------------------------------------------------------------ |
| 0s                 | Market PDA exists, mints exist, vault exists. Mints will fail because oracle TWAP not populated. |
| \~30s              | Keeper has pushed enough observations to populate TWAP. Mints succeed at NAV.                    |
| \~1 min            | Books pinned by the keeper. Instant + committed trading viable.                                  |
| \~5 min            | Keeper's first risk-state mirror and rebalance pass. Capital allocated.                          |
| \~30 min           | Slow floor warming from Benchmarks backfill; spreads settle to steady state.                     |
| \~1 hour           | Steady state - mints, redeems, trades all functional.                                            |

A user **could** mint during the warm-up window (between t=0 and the first TWAP population) but `OraclePriceUnavailable` will reject. Safe to assume markets need \~5 minutes warm-up after listing.

## Adding to the registry

The registry is updated separately from market initialization:

```
SYMBOL=NVDA bun run scripts/register-market.ts
```

This calls `registry::register_market` with the new mints and pools. After this, the registry-driven frontend picks the market up automatically.

If you skip registration, the market still works at the program layer - `mint_paired` etc. all succeed. But the official frontend won't know to display it.

## Adding to the asset list (frontend)

The frontend pulls market metadata from `frontend/lib/market-addresses.json`. After listing:

1. Update the JSON with the new market's pubkeys.
2. Add SEO metadata, asset description, icon URL.
3. Push the change → docs and frontend redeploy.

For private deployments, the structure of `market-addresses.json` is:

```json theme={null}
{
  "cluster": "devnet",
  "usdcMint": "...",
  "markets": {
    "NVDA": {
      "symbol": "NVDA",
      "name": "Nvidia",
      "marketPDA": "...",
      "longMint": "...",
      "shortMint": "...",
      "oracle": "...",
      "collateralVault": "...",
      "liquidity": { "primaryVenue": "nativeClmm", "longPool": "...", "shortPool": "..." },
      "initialPrice": 120,
      "clp": { "pda": "...", "vault": "...", "oiCap": 250000000000, ... }
    }
  },
  "globalClp": { "pda": "...", "vault": "..." },
  "programIds": { ... }
}
```

## Pausing / delisting a market

Soft pause:

```
SYMBOL=NVDA bun run scripts/set-market-active.ts ACTIVE=false
```

This flips `Market.is_active = false`. All mints and redeems reject with `MarketNotActive`. Existing positions remain valid SPL tokens but cannot be redeemed at NAV until the market is reactivated.

Full delist (recover all capital, close pools):

1. Sweep the books back to CLP custody (`pool_sweep_usdc` / `pool_sweep_synth`).
2. Redeem CLP PDA's L+S balances back to cUSDC.
3. `return_to_global` per-market vault → `GlobalClp`.
4. `set_active(false)`.
5. Optionally remove from registry.

The delist procedure is a several-script sequence; see the [Operations runbook](https://github.com/continuum-markets/continuum/blob/main/docs/OPERATIONS.md) for current commands.

## Future: governance-driven listing

When CNTM governance is activated:

1. Anyone can propose a new market listing on-chain.
2. CNTM holders vote with their staked CNTM weight.
3. Quorum reached → proposal queues for execution.
4. Time-locked execution → the listing scripts run automatically.

The same operational steps as above; just behind a vote. Until then, listings are operator-driven.

## See also

<CardGroup cols={2}>
  <Card title="Live markets" icon="address-book" href="/markets/live">
    Markets currently active on devnet.
  </Card>

  <Card title="Roadmap" icon="map" href="/markets/roadmap">
    Planned markets.
  </Card>

  <Card title="Concepts → Markets" icon="book" href="/concepts/markets">
    Market structure, OI cap, account layout.
  </Card>
</CardGroup>
