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
| Constitution | Done. CLAUDE.md — comms style, design laws, hard rules, the consolidated trap list |
| Process | Done. notes/PROCESS.md — the loop, environments, the task interface, CI/CD |
| Decisions | notes/DECISIONS.md — D1–D40 settled; O1–O4, O7–O12, O15, O17 (holders only) and O18 open (O5, O13, O14, O19 answered; O6 half) |
| Plan | notes/PLAN.md — the 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 |
| Features | notes/FEATURES.md — what v1 does, stage by stage. All five stages are built, bar deliberate deferrals. Scope narrowed by D26 |
| Vision | Written. notes/VISION.md — milestone one, the three seams, positions, gacha, composable pairing |
| References | notes/references/ — Uniswap v4, pump.fun, pons, par, Reality rTokens, Robinhood stock tokens |
| Skills | Done. arbitrum-developer (lifted from ../launchpad), foundry-workflow (written here) |
| Plugins | Installed: uniswap-hooks, uniswap-trading, uniswap-viem, uniswap-permissioned-pools, building-secure-contracts, frontend-design |
| Task interface | Done. Makefile — plus dev-anvil, dev-deploy, dev-smoke, dev-smoke-modules (13 steps, all three seams, alone and combined), and check-boundaries (D19) |
| CI | Three 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/ |
| Docs | Docusaurus, 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 handoff | Mechanised. SessionStart hook opens; /handoff closes (D11) |
| Contracts | Launch 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 modules | Live 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 |
| Web | app/ 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 |
| Design | tmp/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 |
| Shipping | Vercel, 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 Sepolia | Redeployed 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) |
| Metadata | Supabase, 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) |
| Services | Built. 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) |
| Stylus | Still 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/assets — BasketWrapper 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 Uniswap | Done. 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 anything | Done, 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 pairs | Done 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 checkdoes not knowapp/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:
- 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 inTHREAT-MODEL.md— caps do not bind PoolManager claims, 640k gas per transfer, and whether to cap a 99% sell tax. - 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).
- Stock and basket pairing are deployed nowhere (D31) — milestone one's items 4 and 5 exist only in code and tests.
- 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
BasketFactoryorsetQuoteSource(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.distributehands a strategy every launch's fees in that currency. Same root cause as O17. launchOfrecords neither the migrator nor the module. Both are readable through the curve.LaunchLenscloses this without touching the factory (PLAN.mdS1, 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.mdstill describes a hookless pool,FEATURES.mdclaims Uniswap's interface quotes our pools,FeeVault.onFeeReceivedis reachable from nothing in production, and the hook miner has no guard against the0x91prefix D15 forbids. .envholds 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.