Skip to main content

Status

Stadium is a launchpad for experiments (D26): a token launches on a bonding curve, trades on it, and graduates itself into a permanently locked Uniswap v4 pool. A launch may attach modules — contracts that run inside its trades on the curve, in the pool and on every transfer — one or several at once. The contracts have been live on Arbitrum Sepolia since 17 Sep. The launchpad as a product is now built and proved locally: a Rust indexer, a Supabase schema, and eleven screens against a seeded local chain of 305 launches. Phases 0 to 3 of notes/PLAN.md are done. Nothing of it is deployed anywhere — that is Phase 4, and notes/DEPLOY-STAGING.md is its runbook.

Read this first, every session. If it disagrees with the repo, the repo wins and this gets fixed.

Where it stands

ConstitutionDone. CLAUDE.md — comms style, design laws, hard rules, the consolidated trap list
ProcessDone. notes/PROCESS.md — the loop, environments, the task interface, CI/CD
Decisionsnotes/DECISIONS.md — D1–D40 settled; O1–O4, O7–O12, O15, O17 (holders only) and O18 open (O5, O13, O14, O19 answered; O6 half)
Plannotes/PLAN.mdthe document to come back to. The v1 cut, a frozen spine, and thirty-odd stages across five phases. Phases 0–3 done; Phase 4 (staging) and Phase 5 (docs) remain
Featuresnotes/FEATURES.md — what v1 does, stage by stage. All five stages are built, bar deliberate deferrals. Scope narrowed by D26
VisionWritten. notes/VISION.md — milestone one, the three seams, positions, gacha, composable pairing
Referencesnotes/references/ — Uniswap v4, pump.fun, pons, par, Reality rTokens, Robinhood stock tokens
SkillsDone. arbitrum-developer (lifted from ../launchpad), foundry-workflow (written here)
PluginsInstalled: uniswap-hooks, uniswap-trading, uniswap-viem, uniswap-permissioned-pools, building-secure-contracts, frontend-design
Task interfaceDone. Makefile — plus dev-anvil, dev-deploy, dev-smoke, dev-smoke-modules (13 steps, all three seams, alone and combined), and check-boundaries (D19)
CIThree workflows: contracts.yml runs and is green; services.yml (Rust) and supabase.yml (replay from zero, type drift) are written and have never run. No web job by choice (D30). make check still points at web/ and has never typechecked app/
DocsDocusaurus, live at docs.stadium.money (Vercel stadium-docs, CNAME + ownership TXT at Namecheap, 21 Sep). The public half is written. /internal 404s there, because the project builds with the framework default rather than docs/scripts/vercel-build.sh, so DOCS_INTERNAL=1 is never set — the branch split D30 describes is not actually wired up. notes/ is still public (D8) wherever it is served; treat it as published writing
Session handoffMechanised. SessionStart hook opens; /handoff closes (D11)
ContractsLaunch to traded pool, against tokens, stocks and baskets, with creator fees on the curve and in the pool, a router, and per-launch modules. 256 local tests plus 17 against live Arbitrum One; 12 invariants over 8,192 calls, with fee recipients randomly blocked
Hooks and modulesLive on Sepolia (D32). LaunchHook is one permanent address every launch's pool carries, mined for 11 flags including all four return-delta ones; ILaunchModule is the seam behind it, running on the curve, the pool and every token transfer. Five modules: tax, anti-snipe, graduation protection, maximum trade size, maximum wallet — nobody exempt from the last two. ModuleSet runs 2 to 10 at once. These pools are absent from Uniswap's own interface until the allowlist clears the delta flags. See notes/sessions/hooks.md
Webapp/ is the interface: a front page that is the hero and the catalogue, a token page with a live chart and trade panel, create, portfolio, watchlist, the lab and an FAQ. React + Vite + wagmi, one chain layer, one token layer (D37). Responsive to 320px in both themes. Rebuilt to the approved design on 21 Sep — see notes/sessions/redesign.md, which also lists the six things that were removed with it. The wallet write path has never been exercised — every trade and launch is simulated, never sent. web/ is the old Mantine interface, still deployed, to be retired
Designtmp/latest-design/ is the approved pack (gitignored). Its palette, type and glass are in app/src/theme/tokens.css, read from the built page's computed styles rather than from its stylesheets — those are a dozen last-wins layers and disagree with what the browser paints. Helvetica Neue at 14px, gold #c5a46a as the accent, teal #2d595f under translucent panels. The lab's card illustrations are not drawn yet: app/src/assets/mechanics/README.md is the slot's contract
ShippingVercel, from master (D30). The live projects still build the old web/ and docs/ under their richcat- names. Decided 21 Sep 2026: a new project for app/, and the old one retired with web/
Arbitrum SepoliaRedeployed 17 Sep 2026 with the hook and modules, then two cohort upgrades on 18 Sep via contracts/ops/sepolia.sh upgrade. WETH only, graduates at 0.01 WETH. Addresses in contracts/deploy/421614.json (committed, D29); factory 0x9f3e…1a24. Launches before each upgrade keep their modules for life (D12)
MetadataSupabase, project ref vbtioxfmmayjbhnbhzsp, already linked. Six migrations locally; the project has only ever served launch_metadata for the old interface, so what it actually has must be read with supabase migration list before anything is pushed (D35)
ServicesBuilt. A Rust indexer — durable cursor, backfill, tail, reconciliation sweep, 15 tests including replay idempotence. Derives candles, holders, positions and curve state in SQL. Runs locally from a native build; the Docker image and docker-compose.staging.yml exist and have never been deployed. Nothing settles against it (D38)
StylusStill nothing that earns it (O6)

Bring it up

git submodule update --init --recursive
yarn install # JS workspaces: docs/ and web/
make dev # the whole local stack: chain, launchpad, indexer, app on :5175
make dev-curate # the podium and endorsements, once the indexer has caught up
make check # fmt, boundaries, lint, build, test -- green, and entirely offline
ARB_RPC=... make test-fork # the same paths against live Arbitrum One. See the note below
make docs # the documentation site on :3000

# the concept, running:
make dev-anvil # a bare local chain on :8545. No fork, no RPC
make dev-deploy # Uniswap v3 (from source), dev markets, then the launchpad
make dev-smoke # launch, buy and sell with ETH, graduate, trade in the pool, split the fees

The core is LaunchFactory, BondingCurve, LaunchToken, PoolMigrator and FeeVault. Pairing lives apart in src/assetsBasketWrapper and BasketFactory — and reaches the core only through IQuoteSource; make check-boundaries fails if either side imports the other (D19). A creator picks a name, a symbol, a pairing and optionally their own fee; the launch trades on a curve, closes at its threshold, graduates into a real Uniswap v4 pool and trades there.

make check needs no RPC. make test-fork runs against the live Arbitrum One singleton and SwapRouter02, pinned at blocks 504,000,000 and 504,491,782 — 17 tests, verified passing 15 Sep 2026. It does not read the root .env: forge runs in contracts/, so ARB_RPC has to be exported or setUp() fails.

The three things v1 has to prove

1. Launch on a curve, migrate to UniswapDone. Proved locally, on a real PoolManager, and on a fork against the live singleton. Graduates inline at a wallet's own gas estimate (D23)
2. Pair against anythingDone, stocks included. Any fixed-balance ERC20 the owner registers: proved at 2–24 decimals, USDT-shaped, and real WETH, wBTC and USDC. Tokenised stocks pair only through a wrapper (D18), because every one on Arbitrum rebases balanceOf. Proved against real rNVDA through Reality's own split and pause
3. Composable pairsDone as a product. BasketFactory deploys a basket from a creator's weights (≥10% each, sized by owner-set reference units), one per composition, and answers the launch factory for it — no owner registration per basket (D20, D21). Curated baskets are an owner flag. Multi-stock baskets proved with mocks; real rTokens one at a time

The router (src/router, D22) takes ETH or any token along a Uniswap v3 path the caller picks, into a launch's curve or — the same call — its v4 pool once graduated, and back out. One shared router, UUPS and owned; never load-bearing. Stock- and basket-paired launches do not route: no contract of ours can acquire rTokens, and Reality onboarding is dropped for v1. They are reachable only by rToken holders.

Curve fees are the protocol's (owner-set, zero by default) plus the creator's (D17), together at most 10% each way. Both are pushed on every trade; a share whose recipient is blocked — USDC and rTokens can block addresses — is held and retried by anyone, so no recipient can stop trading.

Pool fees are split per launch when anyone calls collectFees (D25): the creator's share — 50% to start, owner-set for future launches, snapshotted into each pool — to the creator's fee wallet, the rest to the vault, with the same held-and-retryable fallback. Only a launch's own curve can seed its pool (D24).

What is next

Phase 4: staging. notes/DEPLOY-STAGING.md is the runbook — the order, what has to be supplied, and the one decision that is permanent. The thread is notes/sessions/staging-deploy.md.

Sepolia contracts first, because everything else needs their addresses; then Supabase, then the indexer on Contabo, then Vercel. CI can go any time.

Two things to clear before or during it:

  • The wallet write path has never run. Buying, selling and launching are simulated against the local chain and correct there, but writeContract → receipt → invalidate has not been exercised once. Ten minutes with a wallet on the local chain.
  • make check does not know app/ exists, so CI has never typechecked the new interface.

Local is still the only environment any of the product runs in.

How we got here

The product changed on 15 Sep 2026 (D26): a launchpad for experiments. We build capabilities — a per-launch hook, fee destination and observer, isolated per launch — and experiments build mechanics. The hooks thread closed 18 Sep 2026 (notes/sessions/hooks.md): every launch carries a charging hook and picks modules (D32), live on Sepolia. The MVP (15 Sep) and the testnet interface came before it. The security pass closed 19 Sep (notes/sessions/security.md, notes/THREAT-MODEL.md): five findings fixed and merged, not yet on Sepolia — by choice; ship with SHIP_HOOK=1 ./ops/sepolia.sh upgrade.

Stage 4 closed 15 Sep 2026 (notes/sessions/stage-4-pool.md): pool fees split between creator and protocol (D25), and a hole closed that let anyone strand a raise by seeding its pool with dust (D24). Holder payouts and time weighting left scope under D26.

Stage 3 closed 15 Sep 2026 (notes/sessions/stage-3-graduation.md): a crossing buy sent at its gas estimate used to defer graduation and freeze the launch; it now reverts short of the gas, so estimates include graduation (D23). Permissioned-pool graduation left v1. Stage 2 (the router) closed the same day, stage 0 on 13 Sep, stage 1 on 14 Sep. The security pass closed 19 Sep.

Work is organised in five stages from FEATURES.md, one thread each. A stage session writes its findings into its own thread file and commits them; the coordinating job is then reading that, updating this file, and writing the next brief.

What remains, and the things nothing can reach yet:

  1. Sepolia runs code with known bugs (S2, S3), deliberately, until the next upgrade. The fixes are on master. The pass was internal, not an audit; open limits are in THREAT-MODEL.md — caps do not bind PoolManager claims, 640k gas per transfer, and whether to cap a 99% sell tax.
  2. The fee sink is still global and the vault accounts per currency, not per launch (O17). Modules route their own fees per launch; LP fees still reach the creator and the vault (D25).
  3. Stock and basket pairing are deployed nowhere (D31) — milestone one's items 4 and 5 exist only in code and tests.
  4. Dividends are parked (O18). A wrapper can receive Reality's USDT, but someone has to submit each claim with a proof from Reality's API.

Known loose ends

  • The deploy script covers the core, not stocks. It deploys the router, the quotes and fees, but not BasketFactory or setQuoteSource (the stocks effort, D31). Sepolia has no tokenised stocks either, so that sprint needs stand-ins or fork tests.
  • Slither: 18 Sep 2026, 0 medium or high; 36 low and 12 informational, all known classes. The core's triage is in notes/sessions/mvp-local.md. CI's job had been failing on Mediums since the scaffold — now passes. CI results themselves have still not been checked.
  • Reality's rToken implementation is unverified. Everything we know about it is from resolved selectors, its transactions and fork probes. Its beacon is upgradeable by a 3-of-5 Safe, so any of it can change; the fork tests pin a block and would not notice.
  • The fee strategy seam does not yet meet its own isolation rule. FeeVault.distribute hands a strategy every launch's fees in that currency. Same root cause as O17.
  • launchOf records neither the migrator nor the module. Both are readable through the curve. LaunchLens closes this without touching the factory (PLAN.md S1, stage 1.1).
  • Seven places the notes or the code disagree, found reading the repo on 20 Sep 2026 and listed in notes/sessions/stadium.md. All cheap, none urgent: ARCHITECTURE.md still describes a hookless pool, FEATURES.md claims Uniswap's interface quotes our pools, FeeVault.onFeeReceived is reachable from nothing in production, and the hook miner has no guard against the 0x91 prefix D15 forbids.
  • .env holds a free-tier Alchemy key on a fresh account, for fork tests. Gitignored.
  • The template idea — extracting this foundation as a reusable multi-stack starter — is parked deliberately. Extract later from what survives use; do not abstract early.