Everything about fair-launching a coin on Robinhood Chain — the curve, graduation, fees, and the contracts that make the liquidity un-ruggable.
lunch is a fair-launch coin platform on Robinhood Chain. Anyone can mint a coin in one transaction — no presale, no team allocation, no insider pricing.
Every coin's entire supply is placed as a single full-range Uniswap V3 position at launch, with the LP locked forever from block one. As people buy, the price climbs a smooth curve. Once about 4 ETH of buys sit in the pool, the coin graduates. Creators earn a share of every trade's fee — for as long as they're the coin's creator.
Hit Launch a coin, fill in a few fields, and confirm one transaction. That's it — your coin is live and tradable.
Minting the coin and seeding its initial liquidity band both happen in that single transaction. There is no launch fee — you only pay gas.
At launch, the entire supply is placed as one single-sided full-range Uniswap V3 position. The pool starts with only your token and no ETH, so every buy walks the price up a smooth curve — and because it's one continuous range, the book keeps deepening as the coin grows instead of thinning out.
This is real on-chain liquidity from block one: anyone can buy or sell at any time through the trade router. The token itself is a plain, immutable ERC-20 — no transfer restrictions, no max-wallet, no admin, no mint. Fairness comes from the curve, not from gating your token.
When roughly 4 ETH of net buys sit in the pool, the coin graduates — a milestone marking real, sustained liquidity. Nothing has to move: the LP NFT lives in the FeeLocker from the moment of launch, so liquidity is locked from block one, not at graduation.
The coin trades like any normal V3 pair the entire time, with deep two-sided liquidity that grows as it does. The locked LP means nobody can pull liquidity — the rug is physically impossible.
The board's GRADbadge comes from our indexer and, once earned, stays on — a permanent record of the milestone. If you'd rather check the live number yourself, a standalone, ownerless graduation oracle contract reads it straight from the pool on demand: no admin, no upgrade path, nothing to trust but the math. Since it reads the CURRENT pool state rather than a saved flag, it can read below 4 ETH again after very heavy selling — see For developers for how to call it.
Every trade pays a 1% fee, split three ways:
Your 0.5% accrues in both tokens — WETH from buys, and the coin itself from sells — so a claim pays out both sides. It accrues continuously and is claimable any time from the Claim fees button or your coin's page, paid straight to your wallet. From either place you can also route it across multiple wallets, or reset it back to yourself.
Alongside the fair launch, you can launch a V4 tax coin — the same locked-liquidity, immutable-token guarantees, but on Uniswap V4 with a buy/sell tax you set and optional holder rewards.
Claim your accrued tax any time from your coin's page. The buy/sell tax is shown on the board and on each coin's page, so traders always see it up front.
By default a coin is paired with ETH. But you can instead pair it with a Robinhood stock (AAPL, TSLA, NVDA, GME…), with USDG, or keep ETH — right from the launch screen, for either a V3 fair launch or a V4 tax launch. The coin trades against that asset instead of ETH.
Pair coins are auto-verified on the explorer and appear on the board with a ⇄ pair badge showing which asset they trade against.
A V4 stock/USDG-pair coin can also pay holder rewards — like the ETH-native V4 dividends above, but denominated in the pair asset(s) instead of ETH. Two modes, on top of the usual buy/sell tax:
Set this up on the launch screen's Holder rewardsselector once you've picked a stock/USDG pair under V4 — it only appears for pair coins, since plain ETH V4 coins use ETH dividends instead.
A standalone, trustless utility for locking or vesting any ERC-20 — not just lunch coins. Useful for a creator who wants to publicly lock a chunk of their own supply, or vest team/investor allocations, without trusting a third-party locker.
Fully on-chain and non-custodial — the contract holds the tokens, nobody (including us) can access a lock or vest early. See the Token locker address under Contracts, and its ABI, for the exact lock / createVest / claimVest / transferVest signatures.
Deployed on Robinhood Chain (chain id 4663). Verify anything on the explorer.
lunch is fully on-chain and standard Uniswap V3 — trading terminals, indexers, and bots can integrate permissionlessly.
Find new coins — watch these events on the launcher:
V3TokenLaunched(address indexed token, uint256 indexed tokenId,
address indexed creator, address pool, uint24 fee)
V3TokenMeta(address indexed token, address indexed creator,
string image, string banner, string description,
string website, string twitter, string telegram)Trades are the standard Uniswap V3 Swap event on each pool. Creator handoffs (community takeovers) emit TokenCreatorSet(token, from, to) on the fee locker.
V4 tax-launch coins emit TaxLaunch(...) + V4TokenMeta(...) on the V4 launcher; trades are the V4 PoolManager Swapevent keyed by the coin's poolId. Read a coin's live tax from the hook — hook.config(poolId) → (creator, buyBps, sellBps).
TaxLaunch(address indexed token, address indexed creator,
uint256 supply, int24 launchTick, uint256 devBuyEth)
V4TokenMeta(...) // same shape as the V3 event aboveClaiming V4 tax — unlike V3 (where collectAll pays out directly), V4 tax uses a two-step accrue → claim ledger. Tax skims into accruedEth[poolId] on every swap; a separate, permissionless distribute(poolId) call splits it 80/20 (creator/platform) into a pull ledger, owed[recipient]; each recipient then calls claim() to withdraw their own balance. Anyone can call distribute — a keeper, a bot, the creator, us — it always pays the correct pre-configured creator/platform addresses no matter who triggers it.
hook.accruedEth(bytes32 poolId) view -> uint256 // skimmed, not yet distributed hook.distribute(bytes32 poolId) nonpayable // permissionless — splits accrued into owed[] hook.owed(address recipient) view -> uint256 // your claimable balance, across ALL your pools hook.claim() nonpayable -> uint256 // pays msg.sender their full owed[] balance // creator can retune their own rate any time (same 5%/side cap as launch): hook.setRates(bytes32 poolId, uint16 buyBps, uint16 sellBps) nonpayable
Note: owed[recipient] is a single global balance per address, not per-pool — if a creator has launched multiple V4 coins, one claim() call withdraws everything owed across all of them at once.
Trade — through the router, or the V3 pool directly (1% fee tier, coin/WETH):
// buy — send ETH LunchTradeRouter.buy(address token, uint256 minTokensOut) payable // sell — approve the router first LunchTradeRouter.sell(address token, uint256 tokenAmount, uint256 minEthOut) // quotes for slippage / minOut (view — eth_call) LunchQuoter.quoteBuy(address token, uint256 ethIn) -> tokensOut LunchQuoter.quoteSell(address token, uint256 tokenAmount) -> ethOut
Price & market data— read it live per coin from the launches table (price, market cap, 24h/7d/30d volume, liquidity, holders, bonding progress, graduated, socials), or on-chain: price from the pool's slot0.sqrtPriceX96(market cap = price × 1e9, supply is a fixed 1,000,000,000). Find a coin's pool from the launch event or factory.getPool(coin, WETH, 10000).
Metadata — logo, banner and socials are on-chain in the V3TokenMeta event at launch, or via token.tokenURI().
Safety— every coin is a plain, immutable ERC-20: no owner, mint, pause, blacklist, max-wallet or transfer tax, and the LP is locked from block zero. Heads-up for honeypot scanners: OpenZeppelin's infinite-approval gas optimization (the if (allowance != max)branch) is sometimes misread as a "trade restriction" — it's a false positive, sells work on-chain.
Graduation, checked on-chain— the graduation oracle above is a standalone view-only contract (no owner, no upgrade path, holds nothing) that reads a coin's live net-raised ETH straight from its pool — independent of the indexer, callable by anyone at zero gas cost via eth_call. It reads the current state, not a saved flag, so a coin can read below 4 ETH again after heavy selling (the board's badge, once earned, stays on — this doesn't).
// V3 coins — pass the locker your coin's launches.fee_locker points to GraduationOracle.wethPrincipal(address locker, address token) view -> uint256 // wei GraduationOracle.isGraduated(address locker, address token) view -> bool // V4 (tax-launch) coins — pass the LP locker + the coin's Uniswap V4 PoolKey GraduationOracle.ethPrincipalV4(address locker, PoolKey key) view -> uint256 // wei GraduationOracle.isGraduatedV4(address locker, PoolKey key) view -> bool
V4 tax-launch coins — pool, price & trading. A V4 coin trades on a Uniswap V4 native-ETH pool behind the shared tax hook. Derive its poolId from the PoolKey, read price from the PoolManager, and swap through the UniversalRouter + Permit2:
// PoolKey — currency0 is native ETH (address(0)), currency1 is the coin
key = { currency0: 0x0, currency1: coin, fee: 3000, tickSpacing: 200, hooks: <V4 tax hook> }
poolId = keccak256(abi.encode(key)) // bytes32
// live price + tax (view / eth_call)
StateLibrary.getSlot0(PoolManager, poolId) -> (sqrtPriceX96, tick, ...)
price_eth = 1 / (sqrtPriceX96 / 2**96)**2 // ETH per coin (mcap = price × 1e9)
hook.config(poolId) -> (creator, buyBps, sellBps, configured) // the buy/sell tax, in bps
// trade via UniversalRouter.execute(commands, inputs, deadline)
commands = 0x10 // V4_SWAP
actions = 0x060c0f // SWAP_EXACT_IN_SINGLE, SETTLE_ALL, TAKE_ALL
// buy : native ETH in -> coin out (send msg.value = ethIn)
// sell: coin in -> ETH out (approve coin to Permit2, then Permit2 -> UniversalRouter, first)The tax is taken by the hook inside the swap (creator keeps 80%, platform 20%); there's no separate transfer tax — plain wallet-to-wallet sends are untaxed.
Stock / USDG-pair coins.A coin can be paired with a Robinhood stock or USDG instead of ETH. These launch from the separate stock/USDG-pair launcher and live in a single-sided full-range Uniswap V3 coin/<pairToken> pool (1% tier) — not a coin/WETH pool — locked in the pair fee locker.
V3PairLaunched(address indexed token, uint256 indexed tokenId,
address indexed creator, address pool, uint24 fee,
address pairToken, int24 launchTick)
V3TokenMeta(...) // same shape as the ETH launcherlaunchPair(name, symbol, totalSupply, fee, address pairToken,
uint256 devBuyAmount, uint256 minCoinOut) payable
// + launchPairWithMeta / …Ref / …WithMetaRef
// atomic ETH-funded dev buy (value = launchFee + devETH):
launchPairEthWithMetaRef(name, symbol, totalSupply, fee, pairToken,
bytes ethQuotePath, uint256 minCoinOut, Meta, address referrer) payableTrade — route a multi-hop V3 path through the pair token (SwapRouter02), not the ETH-only trade router:
// buy (ETH auto-wrapped): WETH -> USDG -> [stock ->] coin
// sell (reverse): coin -> [stock ->] USDG -> WETH (+ unwrapWETH9)
SwapRouter02.exactInput({ path, recipient, amountIn, amountOutMinimum })
QuoterV2.quoteExactInput(path, amountIn) -> amountOut // slippage / minOutV4 stock/USDG-pair coins. Sibling of the ETH-native V4 launcher paired with a stock/USDG instead of native ETH — same tax mechanics (buy/sell bps, 80/20 creator/platform split, locked auto-compounding LP) plus optional holder rewards paid in the quote asset or a multi-asset basket. currency0/currency1 are {coin, quote} sorted by address (the quote is not always currency1 the way native ETH is always currency0) — invert price accordingly.
PairLaunch(address indexed token, address indexed creator,
address indexed quote, uint256 supply,
int24 launchTick, uint256 devBuyEth)
V4TokenMeta(...) // same shape as the ETH launcher — plain launches only// plain tax, optional atomic ETH-zap dev buy (ethQuotePath empty = no dev buy)
launchPair({ name, symbol, totalSupply, pairToken, buyBps, sellBps,
recipients, splitBps, ethQuotePath, minQuoteOut, referrer }) payable
// + launchPairWithMeta(params, Meta)
// holders earn the pool's own quote token
launchPairRewards({ ...above, rewardsBps }) payable
// holders earn a weighted BASKET of up to 10 assets (bps must sum to 10000);
// a leg's asset === pairToken needs path="0x" (direct); every other leg needs
// a real quote→…→asset V3 path
launchPairRewardsBasket({ ...above, rewardsBps,
basket: [{ asset, bps, path }, ...] }) payableRewards / claim — every rewards or basket coin's token exposes tracker(), its one-shot-linked dividend tracker:
token.tracker() view -> address // 0x0 for a plain (non-rewards) coin tracker.claimableOf(address) view -> uint256 // pending, in the accrual denomination tracker.claim() nonpayable -> uint256 // self-claim only — pulls YOUR balance // basket trackers only: tracker.legCount() view -> uint256 tracker.basketLeg(uint256 i) view -> (address asset, uint16 bps, bytes path) tracker.claimWithMinOuts(uint256[] minOuts) -> uint256 // per-leg slippage floor, same order as the legs
A basket claim converts your accrued quote into each leg's asset at claim time and pays every asset directly — you end up holding several distinct token balances, never netted into one.
Claiming V4-pair tax — same accrue → distribute → claim pattern as ETH-native V4 above, but quote-denominated instead of ETH, and the pull ledger is keyed by both recipient and quote token. config(poolId) also returns a different, larger shape than the ETH-native hook:
hook.accruedQuote(bytes32 poolId) view -> uint256 // skimmed, not yet distributed, in the quote token hook.distribute(bytes32 poolId) nonpayable // permissionless — splits accrued into owed[][] hook.owed(address recipient, address quote) view -> uint256 // your claimable balance, in that quote hook.claim(address quote) nonpayable -> (uint256 amountPaid, address tokenPaid) // claim() tries to convert your owed quote -> WETH via a configured SwapRouter02 path first (tokenPaid // = WETH); on no route or a reverting swap it falls back to paying the raw quote token instead. // config(poolId) — 10 fields, NOT the 4-field shape shown for the ETH-native hook above: hook.config(bytes32 poolId) view -> ( address creator, uint16 buyBps, uint16 sellBps, bool configured, bool autoEnabled, bool quoteIsC0, address quote, address rewardsTracker, uint16 rewardsBps, uint80 autoThreshold )