Docs

Everything runs on Robinhood Chain, an Arbitrum Orbit L2. Gas is ETH and a launch costs roughly 0.00007 ETH.

Deployed contracts
FeeRouter0x7bb88e8ce3bc96
PopsLaunchAdapterV20x9dc6d48e46b251
Uniswap v4 PoolManager0x00000000E08A90
pools.trade LiquidityLauncher0x00004c4c63D4e9
Network
ChainRobinhood Chain
Chain ID4663
Gas tokenETH
DEXUniswap v4
StackArbitrum Orbit L2
Explorerblockscout
Route keys

A creator's identity is a hash, not an account:

routeKey = keccak256(abi.encodePacked(platform, handle))

Handles are lowercased and stripped of their prefix first, so @Vitalik and vitalik resolve to the same route. The contract exposes computeRouteKey() so you can verify any route yourself.

Handle normalization

Applied identically in the browser, the API and the contract. Any difference would produce a route nobody could ever claim.

Trim whitespace, then strip the platform prefix (@, ttv/, yt/, gh/)
Lowercase, then NFC-normalize
Accept only a–z 0–9 _ . -, 1–64 characters
Platform is one of x, twitch, youtube, github
The claim attestation

Claiming is gated by an EIP-712 signature over this struct, signed by the attestor key after Privy confirms the logged-in account owns the handle:

Claim {
  bytes32 routeKey
  address wallet
  uint256 nonce
  uint256 deadline
}

Domain is PopsFeeRouter v1, bound to the chain ID and the FeeRouter address. Nonces are single-use and the deadline is ten minutes, so an attestation can't be replayed or banked for later.

Launching programmatically

The UI is a thin wrapper over one adapter call. Compute the routeKey, then:

LaunchAdapter.launch(
  string  name,
  string  symbol,
  bytes32 routeKey,
  uint16  creatorCutBps,   // 0–9000
  bytes   tokenData,       // (description, link, image, extra)
  bytes32 salt
)

It emits CoinLaunched with the token address. Anything launched directly against the adapter is picked up by the indexer, so it shows up here without touching this site's API.

HTTP API
GET/api/coins

Indexed coins. filter=all|bond|grad, limit, offset.

GET/api/coins/[address]

One coin, including its launcher.

GET/api/stats

Coins launched, routed to creators, creators claimed.

POST/api/launch/prepare

Validates inputs, returns the routeKey. Auth required.

POST/api/launch/confirm

Registers a launched token. Auth required.

POST/api/images

Stores a coin logo, returns its URL. Auth required.

GET/api/claims/me

Routes claimable by the logged-in account.

POST/api/claims/attest

Signs the EIP-712 attestation for a claim.

Authenticated routes expect Authorization: Bearer <privy access token>.

Coin logos

Logos are square-cropped to 400px WebP in the browser, capped at 512 KB, and stored server-side. The resulting URL is written into the token's on-chain metadata as well as the index, so it travels with the coin rather than living only here. PNG, JPEG, WebP and GIF are accepted; animated GIFs are kept as-is.

Glossary
routeKey

keccak256(abi.encodePacked(platform, handle)) — the on-chain identity of a creator before they have a wallet.

creatorCutBps

The creator's share in basis points, 0–9000. Fixed in the launch transaction, never mutable.

attestation

An EIP-712 signature from the attestor key saying "this wallet owns this routeKey". Carries a nonce and a 10-minute deadline.

graduated

A coin whose pool has cleared the launchpad's bonding threshold and trades on the open Uniswap v4 pool.

bonding

The phase before graduation, while the launchpad still holds the curve.

How it worksLaunch a coin