OpenFinance launchpad (the "wrapper") — launch a token on Robinhood Chain (EVM, chain id 4663) with a FEE MODULE that decides, permanently, where its trading fees go. This is the "launch a token that burns its fees / splits them / runs a raffle / pays its holders" tool.
**THIS IS THE DEFAULT LAUNCH TOOL FOR THE PONS CURVE ON ROBINHOOD CHAIN** — a plain launch with nothing said about fees uses module='keep', which sends the fees to the creator's own wallet and is the only module that can be repointed later. Do NOT use openfinance-pons-launch for a new launch; this tool launches on the same Pons curve, with the fee router added, so it is a superset.
**It is not the only launch venue on this chain.** openfinance-launchpad-v4 is a separate product: a launch there IS a real Uniswap V4 position, paired against an approved quote token such as USDG, with a snipe tax and no fee modules. Route to it when the user names Uniswap or V4, names a pair asset like USDG, or wants the token tradable through the Uniswap router. If the user says only "launch a token on Robinhood Chain" with nothing about fee modules or Uniswap, ASK which venue — the pools are not interchangeable and the choice is permanent.
HOW IT RELATES TO openfinance-pons-launch:
• Same chain, same Pons curve underneath, same Privy EVM wallet. The token still trades on Pons.
• This adds a fee router, so fees can be kept, sent to one wallet, split, burned, raffled, or airdropped to holders.
• openfinance-pons-launch remains only for READING Pons state (quote assets, launch terms) and for the fee-claim actions on tokens launched through it BEFORE the wrapper existed. Its launch action is legacy — do not route a new launch to it.
• **Module choices are FROZEN AT LAUNCH**, with one exception: `keep` may be repointed later (`FeeRouter.repointWallet`). A burn, split, raffle or holders module cannot be changed afterwards — no admin key, no migration. Treat those like deploying an immutable contract.
• Every launch keeps 5% of its fee bucket (500 bps) for the keeper's gas. This is not optional and not a platform fee: without it the launch could never have its fees moved, and the keeper refuses to service it. The module gets the other 95%.
MODULES (pick one, frozen):
keep — fees to the creator's own wallet.
wallet — fees to one named wallet (`recipient`).
split — fees divided between 2-16 wallets (`split`), bps totalling exactly 10000.
burn — fees buy the launched token back and burn it.
raffle — fees fund a periodic prize draw among holders (`raffle`, required).
holders — fees airdropped pro-rata to holders (`airdrop`, optional; defaults are sensible).
ROUTING:
• A bare "launch a token" with no fee preference → this tool, module='keep'. Do not ask the user to choose a module they did not raise; `keep` is the plain behaviour and is repointable.
• Call action='get_readiness' first for a raffle launch — it reports whether the keeper and randomness contracts are live, and lists the stock assets a stock-prize raffle may use. A raffle launched without a live keeper would never draw.
• Call action='simulate_launch' before action='launch' for anything non-trivial. It builds and validates the exact transaction without sending it, so a bad split or an impossible raffle fails for free.
• action='list_launches' is the public feed of every launch from this factory, newest first — the "what has been launched" question.
ACTIONS:
launch — { module, name, symbol, description?, logo?, creatorTaxBps, pairToken?, developerBuy?, recipient?, split?, raffle?, airdrop? }:
`module` — one of keep|wallet|split|burn|raffle|holders. Frozen.
`creatorTaxBps` — the TOTAL trading tax in basis points, capped by Pons's live limit. The wrapper's own protocol surcharge is included in this number, not added to it.
`pairToken` — optional; the asset the token trades against (a symbol or address — use openfinance-pons-launch's list_quote_assets to enumerate them, including Robinhood's tokenized stocks). Defaults to ETH.
`recipient` — required for module='wallet'.
`split` — required for module='split': [{ recipient, bps }], 2-16 entries, bps summing to EXACTLY 10000. They do not sum if each share is rounded independently — three equal shares floor to 9999 — so floor each and give the remainder to one recipient.
`raffle` — required for module='raffle'. Frozen terms: cadence, prize pool share, winners per round, ticket size, prize bounds.
**DESTRUCTIVE AND IRREVERSIBLE — launches a real token on mainnet, commits real funds for the launch fee, and freezes the fee module forever.** Show the user: module, resolved pair asset, creatorTaxBps, the 5% keeper slice, and every recipient/share. Require explicit confirmation.
simulate_launch — same arguments as launch: builds and validates the transaction WITHOUT sending it. Returns the resolved allocations, the launch fee and the would-be addresses. Free and safe — prefer it before any launch.
list_launches — { limit?, offset? } (PUBLIC — no auth): every launch from this factory, newest first. Returns { total, tokens: [{ token, curve, creator, name, symbol, router, adapter, raffle, pairToken, launchedAt, feesOwedWei, marketCapUsd }] }. `launchedAt` is a unix second from the launch's own block — a launch carries no timestamp on chain, so this comes from its `Deployed` event. `feesOwedWei` is what its buckets hold but have not yet delivered. `marketCapUsd` is null until a market-cap provider indexes the token, which is normal for a launch still on its bonding curve with no DEX pair.
get_launch — { token } (0x… address): one launch's fee module and routing, read from the contracts. Returns its module, buckets, allocations, router, adapter and raffle.
get_funding — { token } (0x… address): why a launch's fees have or have not moved. Returns { paidWei, spentWei, fundingWei, ledger }. `paid` is on chain (what the router has sent the keeper hub); `spent` comes from the keeper's own ledger. The keeper cranks a launch only when the fee covers the gas, so `fundingWei` is the number that explains a launch whose fees appear stuck. `ledger: null` means the keeper has never worked this launch, so spend is zero.
list_creator_launches — { creator } (0x… address) (PUBLIC — no auth): every launch by one creator, with the same enrichment as list_launches.
get_raffle — { raffle } (0x… address): a raffle's live state — current round, cadence, prize terms, and whether a round is drawable.
get_raffle_claims — { raffle, wallet, round? }: a holder's claimable prizes with their Merkle proofs. The proofs come from the keeper's database; whether a slot is already PAID comes from the contract, which is authoritative.
list_raffle_stocks — {} (PUBLIC — no auth): the tokenized-stock assets a stock-prize raffle may pay out in.
get_readiness — {} (PUBLIC — no auth): whether a raffle can be launched at all in this environment — keeper hub, randomness contract, and whether the hub owner has paused launches. Call before offering a raffle launch.
get_keeper_status — {} (PUBLIC — no auth): a deployment check, not launch data. Reports whether this host can reach the keeper's database and whether the keeper is alive. An unreachable database is a SUPPORTED state — proofs fall back to a slower rebuild from transfer history — so `configured: true` with `reachable: false` means proofs still work but the indexed path is not in use.
**⚠️ SAFETY** — launch is irreversible, commits real funds, and freezes the fee module permanently. Always simulate_launch first, show the resolved allocations including the 5% keeper slice, and get explicit confirmation.