Developers
Everything below is public and permissionless. You do not need an API key, an allowlist, or our cooperation to build on any of it.
Chain
| Network | Robinhood Chain (Arbitrum Orbit L2) |
| Chain ID | 4663 |
| RPC | https://rpc.mainnet.chain.robinhood.com |
| Gas token | ETH |
The public endpoint rate-limits heavy clients and keeps only a few thousand blocks of history, use an archive provider for indexing or fork testing.
Contracts
| PopLaunchFactory | 0x4615…b440 |
| PopQuoteRegistry | 0xA2E2…966D |
| PopHook | 0xf91f…2044 |
| PopLocker | 0x600e…5095 |
| PopFeeEscrow | 0xA919…D5ff |
| PopSwapRouter | 0x8247…88d9 |
| Uniswap V4 PoolManager | 0x8366…0951 |
Per-launch token addresses come from the factory's TokenLaunched event, or getLaunchedToken(token). Sources are verified. See /proof.
Trading a launch (bots start here)
Every launch is a standard Uniswap V4 pool on the canonical PoolManager from its first block, quoted in WETH, fee 0, tick spacing 200, hooks = PopHook, currencies sorted by address. If your stack can swap Uniswap V4, you can trade every launch with no integration beyond the pool key. After the bond, the pair is the launch's quote token instead of WETH.
// Pool keys, straight from the factory
factory.curvePoolKey(token) -> PoolKey // WETH pair, live from launch
factory.bondedPoolKey(token) -> PoolKey // quote pair, live after the bond
// Or skip V4 plumbing entirely: the router is one call, ETH in / ETH out,
// and routes the right pool (and the quote conversion, post-bond) itself.
router.buyWithEth(token, minTokensOut, deadline) payable -> tokensOut
router.sellForEth(token, tokenIn, minEthOut, deadline) -> ethOut // approve token first
// Full launch record: creator, quote, phase (0 Trading, 1 Bonded), fee terms
factory.getLaunchedToken(token) -> LaunchedToken
// Holder rewards (only on HolderRewards launches)
rewardToken.claimable(account) -> uint256
rewardToken.claim()
rewardToken.sync() // permissionless; credits any new inflowThe launch-window snipe tax (99% decaying to 0 over ~3 seconds) is charged by the hook on every route, so sniping the launch second is unprofitable by design, whatever router you use.
Anyone-can-call functions
These are not privileged. If you run a keeper or a bot, these are yours to call:
factory.isBondReady(token): true once the curve range has filled.factory.bond(token, minQuoteOut): convert the raise into the quote (bounded by the quote's 30-minute TWAP on top of your own floor) and seed the locked pool. Atomic and retryable forever.hook.sweepPoolFees(poolId, minOut): settle a pool's pending fees, burns and rewards (the conversion-bearing sweeps are operator-gated; quote-side sweeps are open to the creator).registry.listQuote(token, adapterId): list any qualifying quote token.registry.repegQuote(token): refresh a quote's peg (once per day, clamped).rewardToken.sync(): credit rewards that have arrived.
Indexer API
A Ponder indexer serves the data this site runs on. It is read-only and open.
GET https://ponsonpons-production.up.railway.app/quotes
GET https://ponsonpons-production.up.railway.app/launches/<token>/trades
GET https://ponsonpons-production.up.railway.app/launches/<token>/candles/<60|900|3600|86400>
POST https://ponsonpons-production.up.railway.app/graphql # full schema
https://ponsonpons-production.up.railway.app/sql/* # @ponder/client live queries (SSE)Prices are stored as quote-per-token scaled by 1e18. Rows carry a denom field: 0 means WETH (the curve phase), 1 means the launch's bond quote. USD conversion is deliberately left to the consumer rather than baked into the data.
Events worth indexing
PopLaunchFactory: TokenLaunched, LaunchBonded, DevBuyExecuted,
BondTokensPermanentlyLocked,
CreatorFeeRecipientUpdated, LaunchBondRescued
PopHook: PoolRegistered, HookFeeCollected, SnipeTaxCharged,
BondReady, PoolFeesSwept, PoolQuoteBurned,
PoolHolderRewardsPushed
Uniswap V4 PoolManager: Swap (filter by the launch's pool ids)
PopQuoteRegistry: QuoteListed, QuoteRepegged, QuotePausedUpdated
PopLocker: PositionLocked, TokenSupplyLockedBondReady is the one to alert on: the curve has filled and bond(token, minQuoteOut) is waiting for its first caller. The first PoolRegistered for a token is its WETH curve pool; the second (at the bond) is its quote pool.
Something unclear or wrong? The contracts are the source of truth, and every claim here is checkable on /proof.