Skip to main content

Session — stage 2, life on the curve — closed 15 Sep 2026

How a buyer gets into a launch without already holding its quote asset. Everything in stage 2 is built except the router (O19): paying in ETH, ARB or USDC and being routed into the curve or pool. Research is done (below). Scope agreed 15 Sep 2026 — D22. Being built.

Read first, in this order

This file, "What the research found"The facts, verified on chain 14 Sep 2026
notes/FEATURES.md — Stages 0, 2 and 4The router line appears in stages 2 and 4; the stage 0 gaps below reach into two ✔ lines
notes/DECISIONS.md — O19, D18, D19, D20, D21The router question and the pairing layer it routes into
../launchpad/src/ZapRouter.solRHUB's live router — the template
contracts/src/curve/BondingCurve.sol, contracts/src/assets/BasketWrapper.solbuy/sell/quoteBuy, and mint/previewMint
notes/references/reality-rtokens.mdWhere rToken liquidity actually is

The uniswap-trading plugin covers the Universal Router, Permit2 and v4 swap encoding.

Already decided — constraints

  • The router is never load-bearing. The curve and pool stay directly callable.
  • SafeERC20 throughout. Trading in the pair itself already works without a router.
  • D19: anything that knows about baskets stays out of the core; make check-boundaries stays green; the stage 0 and stage 1 suites pass unchanged.
  • Curve fees are D17's. A router adds none unless that is decided.

What the research found

Ordinary quotes route today.

  • RHUB's ZapRouter is live: ETH → ARB on Uniswap v3, then the curve or the v4 pool, switching on curve.graduated(). Custody-free, no owner. But per launch, and its v3 leg has no minimum of its own.
  • Uniswap v3 on Arbitrum (balances, not depth): WETH/USDC 0.05% ~6,750 WETH + 19.1M USDC; WETH/ARB ~188 WETH + 8.7M ARB; WETH/wBTC 5,400 WETH + 297 wBTC. ARB/USDC is thin ($5.5k) — route via WETH.
  • Universal Router 0xa51a…81a3, SwapRouter02 0x68b3…Fc45 and Permit2 are deployed.
  • After graduation our pools have no hook, so Uniswap's router and aggregators already reach them. Ours is only indispensable while a launch is on the curve.

Stocks do not route — our contracts cannot acquire rTokens.

  • Reality's docs ("Onchain Swap", /info/ref/protocol/attestation) describe the protocol path: fetch a signed attestation from POST /api/v1/rwa/wallet/attestation, then call TokenManager.mintWithSignature in the same transaction.
  • On chain, mintWithSignature reverts UserNotRegistered for any caller missing from Reality's identity registry 0x36e2D13013b48862A818ec3394826F65c94618d4 — including Bitget Wallet's executor. Reality's own RFQ contract passes that gate and fails only on the signature.
  • Retail buys today go Bitget Wallet router 0x6889… → executor 0xBc1D…c973 → Reality RFQ contract 0xea13017FB146c3245Bc032B5ba590460B01F24B1, whose swap is itself gated by a caller allowlist.
  • So ETH → stock needs Reality to onboard us: KYB for our entity, API keys, our router registered. That is a business dependency, and it makes us the participant routing retail into a product Reality sells only to KYC'd non-US persons — a compliance question, not just an engineering one.
  • Minting is 24/5; a stock route closes at weekends and between sessions (TokenManager.marketHours()).

Gaps this exposed in stage 0 — settle before scoping the router

  1. "Anyone can mint and redeem baskets" is ✔ in FEATURES.md, but only rToken holders can. A contract, a router or a non-Bitget user cannot obtain rTokens on chain. The people who can keep a basket's price honest are, in practice, Bitget users. The marker overstates it.
  2. A stock-paired launch has no on-chain way in for most buyers. Buying needs the basket, the basket needs rTokens, and rTokens come only from Reality or Bitget. Stage 0 proved the mechanism end to end with a whale's rNVDA on a fork; it never asked where a normal buyer's rNVDA comes from.
  3. Both are liquidity and access facts, not contract bugs. No stage 0 contract is wrong; what may be wrong is the claim that stock pairing is usable.

Decided 15 Sep 2026

  • Stage 0 gaps: the mint line in FEATURES.md is ~, caveated to rToken holders. Reality onboarding is dropped for v1, not parked — a stock-paired launch is reachable only by holders.
  • Router scope (D22): ordinary quotes only; a v3 path supplied by the caller plus one final minimum; one shared router, UUPS and owned; excess on a crossing buy refunded in the quote.
  • The developer's frame: build the concept end to end, refine incrementally afterwards. Stage 2 closes when the router lands.

Build plan

  1. Done. Router, curve leg: ETH or token → v3 path → quote → curve.buy, and the reverse. 11 local tests against a mock v3; each guard mutation-checked against the test that names it.
  2. Done. Pool leg: the same calls switch to the v4 pool on curve.graduated(). Proved for a quote sorting either side of the token, each trade equal to a direct swap in that pool.
  3. Done. Fork tests against live SwapRouter02 and PoolManager: ETH into an ARB launch on the curve and in the pool and back to ETH; ARB → WETH → USDC into a USDC launch and back. Every amount exact, each leg measured directly and undone. Block 504,000,000; 0.05% is the deepest tier for both WETH/ARB and WETH/USDC there.

Not this session

Pool fees (O17), hooks, the interface, anti-snipe, security, dividends (O18).

Found while building

  • PartialFill has no test. A swap stopping at the price limit would strand the unspent input, so the router reverts; the migrator's range is full, so draining it is not practical to set up.

Next

Closed. STATUS.md updated; the next thread is the developer's call.