Appearance
BlazLaunch
The stock launchpad. Launch a token whose whole supply trades against a tokenized stock. No liquidity to add; the creator earns 75% of every trade.
Route: /defi/launch · Chains: Robinhood Chain (4663, opens here), Base (8453); Arbitrum and Ethereum next · Venue: Doppler Airlock on Uniswap v4 · Fee: 1% pool fee, split creator 75 / Blazpay 20 / Doppler 5
Priced in, not pegged to
A token launched against NVDA trades in NVDAc. If NVDA rises 10% and nobody trades, the token's dollar price rises 10% while its NVDAc price does not move. Say this plainly whenever someone says "pegged". A 1:1 wrapper is a different product (see the plan, §11).
What it does
The creator names a token, picks the stock it is priced in and the market cap the curve opens at. The backend builds one transaction against Doppler's Airlock, simulates it, and hands it back unsigned. The wallet signs it. That transaction mints the whole supply into a Uniswap v4 pool as single-sided liquidity across three price ranges expressed as market caps. The first buyer brings the stock token and sets the price. Every trade pays the pool fee to the beneficiaries fixed at creation.
There is no graduation and no migration: the pool is on Uniswap from block one.
Stocks you can price in
The allowlist is the LaunchpadStock collection: a Token seeded as an equity that has a Chainlink total-return feed. Today: Robinhood Stock Tokens on Robinhood Chain (35 feeds) and Coinbase B20 stocks on Base (13 feeds). Prices show their source (chainlink, quote, none) and the US market session; off-hours the stock leg is the last print.
Logos are curated, not derived. Every logo URL is fetched once by scripts/launchpad/seed-stock-logos.js and stored only if it returned a real image, because the free equity-logo hosts throttle bursts and a per-request URL would load for one visitor and not the next. Robinhood's own CDN is excluded outright: all 89 of its logo URLs answer 403. A stock with no verified logo shows a lettered mark rather than a broken image.
Trading a launched token
The v4 quoter reverts on Doppler-hooked pools, so a quote is the real Universal Router swap simulated from the user's wallet with eth_simulateV1. What the wallet signs and what the quote says are the same calldata. Approvals (token.approve(Permit2), Permit2.approve(router)) are added as steps only when missing. A wallet that does not hold the stock is pointed at Blazpay swap with the stock pre-selected.
Blazpay does not run these swaps through the BlazpayRelayer; the pool fee is the only fee.
The board lists our launches
Only tokens launched through Blazpay (source: blazpay) appear. The Airlock scan can see every stock-paired pool on a chain — Base has thousands from other launchpads — and listing those would present other people's tokens as ours. Discovery is therefore opt-in (LAUNCHPAD_DISCOVERY_ENABLED=true) and exists for reconciliation and demos; ?includeDiscovered=1 reveals those rows, and the stats jobs skip them so no RPC is spent on pools nothing shows.
Prices and market caps come from PoolManager.extsload of each pool's slot0 every two minutes; trades and 24h volume from the PoolManager's Swap events. That event reports the PoolManager's caller, which is a router for almost every trade, so it is stored as sender; the trader's own address is known only for trades recorded through POST /trades.
The loop: earnings, milestones, sharing
Claiming. Doppler holds pool fees on an accumulator: getShares(poolId, who) is a beneficiary's cut, and collectFees(poolId) sweeps what the pool accrued and settles the caller. It is permissionless and needs no approval. Fees arrive in both currencies, the launched token and the stock it is priced in.
The figure shown to a creator is a MEASURED BALANCE DELTA, not a formula: the backend simulates the creator's own collectFees from their address and reports the change in their two balances, so the number on the page and the transaction they sign are the same measurement. Verified on a live Robinhood Chain pool, where a 95% beneficiary was shown 324,045.9 tokens plus 0.0396 NVDA, exactly 95% of the pool's uncollected 341,100.9 and 0.0417.
Two performance figures, because a token here is priced in a stock. xVsUsd is what a dollar buyer made; xVsStock is what someone who already held NVDA made by holding this instead. They disagree in the interesting case: a token up 20% while NVDA is up 20% has gone nowhere against the thing it is priced in, and only the second number says so. No other launchpad can show it.
Milestones are taken from the launch's own curve and from that comparison rather than round dollar numbers: crossing into curve range two, or beating the stock, are facts about this market. They are sticky, keeping the time first reached, so a dip never un-achieves one.
The share card is rendered live. GET /card/:chainId/:token.png builds an SVG and rasterises it with resvg on every request, so a link posted once keeps showing current numbers. GET /share/:chainId/:token carries the Open Graph tags and bounces people to the app, which is how a single-page bundle gets an unfurl at all: a crawler never runs its JavaScript.
Points
launchpadCreate: 500 once per token. launchpadTrade: 100 per $1 traded, min 5, max 1,000 per tx, shared 50,000/day cap with swaps.
Compliance
Coinbase, Ondo, xStocks and Robinhood restrict who may hold their tokenized stocks by jurisdiction. State-changing routes sit behind a country gate (LAUNCHPAD_BLOCKED_COUNTRIES, read from CF-IPCountry) and the UI shows a one-time disclosure. Nothing is custodied: the server never signs.
Operations
- Open a chain:
node --env-file=.env scripts/launchpad/enable-launchpad-chain.js 4663 --venue doppler --treasury 0x…and setLAUNCHPAD_ENABLED=true. - Choose which chain the launch and board pages open on:
LAUNCHPAD_CHAIN_ORDER(default4663,8453).Network.orderranks chains for the rest of the app, so the launchpad keeps its own order; chains it does not name follow onNetwork.order. - Refresh the allowlist after seeding equities:
scripts/launchpad/seed-launchpad-stocks.js --apply. - Simulate a create without enabling:
scripts/launchpad/simulate-prepare.js 8453 NVDA. - Probe live pools:
scripts/launchpad/probe-pools.js 8453. - Refresh the board by hand (the only way when
CRON=false):scripts/launchpad/sync-now.js [chainId] [--deep]. - Curate stock logos:
scripts/launchpad/seed-stock-logos.js --apply(add--recheckto revalidate stored ones). - Drop discovered rows:
scripts/launchpad/purge-discovered.js --apply.
Full spec and decision log: STOCK_LAUNCHPAD_PLAN.md at the workspace root.