packages/abis/chains.json, a row in the deploy script’s chain table, a deployment, and one keeper and indexer more. Robinhood Chain was added this way; Arc mainnet is registered and waits for its deployment.
What the chain must have
- Cancun EVM. The contracts and Uniswap v4 are compiled for
evm_version = "cancun"and use transient storage (TSTOREandTLOAD) andMCOPY. Arbitrum Orbit (ArbOS 40 and later) and OP Stack chains qualify. Check by executing, not by reading docs. - A dollar stablecoin launches settle in, 6 decimals preferred (USDC, USDG). On a testnet without one,
Deploy.s.solcan deploy a mintable mock (DEPLOY_TEST_DOLLAR=true) and the app offers a “Get test dollars” button for it. - Permit2, canonical
0x000000000022D473030F116dDEE9F6B43aC78BA3on most chains. ThePositionManagerand theLaunchFactoryuse it. - Uniswap v4: either the official
PoolManager,PositionManager,StateViewandQuoter(put them underuniswapV4in the registry and in_defaults, and run the indexer withINDEX_POOL_SWAPS=false, because a sharedPoolManageremits every swap on the chain) or nothing, in which caseDeploy.s.soldeploys its own set and the indexer can index swaps. - An FX price source. The keeper oracle works anywhere; add Pyth (
pythin the registry) or a Chainlink adapter where FX feeds exist. - Optional: EURC or a bridged equivalent (
eurc; without it EUR is simply not registered), Multicall3 (probed at runtime), a Blockscout instance (explorerApi, for verification), a faucet.
Checklist
1
Register the chain
Add an entry to
packages/abis/chains.json. The loader validates it at startup.Required: id, key (slug, used for token-list file names and as the Ponder chain name), name (shown in the UI), testnet, rpc, explorer, nativeCurrency (name, symbol, decimals; the symbol appears in “Gas is paid in …”), gas (maxFeeGwei, priorityGwei; add minBaseFeeGwei only when the chain enforces a floor like Arc’s 20 gwei, which pins the fee in the deploy scripts and is mentioned in the UI), dollar (symbol, decimals, optional address, mintable, logo; leave address out until a mock is deployed).Optional: rpcs (alternates; the indexer and deploy script default to them), ws, explorerApi, eurc, faucet, multicall3, permit2, pyth, uniswapV4, ethGetLogsBlockRange (the public RPC’s limit for the indexer), maxLogAddresses (addresses per log filter), notes.2
Mirror the addresses in the deploy script
Add a row to
_defaults() in contracts/script/Deploy.s.sol with usdc, usdcSymbol, eurc, permit2, pyth and the Uniswap v4 addresses (or testDollarAllowed on a testnet). A chain without a row must pass USDC, EURC (0x0 skips EUR) and PERMIT2 in the environment.3
Deploy
Fund the deployer with the chain’s gas token, then
CHAIN_ID=<id> bash scripts/deploy-testnet.sh (or the mainnet script). It writes packages/abis/deployments/<id>.json; if it deployed a mock dollar, copy that address into dollar.address of the registry entry. See Deploy contracts.4
Run the keeper and the indexer
Keeper with
CHAIN_ID=<id> (pnpm --filter @launchpad/keeper once first so every currency has a rate, then start). Indexer with CHAIN_ID=<id>, PORT=<free port>, PONDER_RPC_URL_<id>, START_BLOCK_<id>=<deploy block> and INDEX_POOL_SWAPS=false on a shared PoolManager. Add both to deploy/ecosystem.config.cjs and a server block or location for the indexer to the reverse proxy.5
Wire the web app
Add a row for the chain id to
RPC_ENV and INDEXER_ENV in apps/web/src/lib/chain.ts (Next.js only inlines literal process.env.NEXT_PUBLIC_* reads), set NEXT_PUBLIC_INDEXER_URL_<id>=<that indexer> (plus NEXT_PUBLIC_RPC_URL_<id> if the registry RPC is not the one to use) and rebuild. The switcher lists the chain as soon as its deployment file exists at build time; NEXT_PUBLIC_CHAIN_ID=<id> only makes it the default.6
Assets
CHAIN_ID=<id> pnpm abis:logos and CHAIN_ID=<id> pnpm abis:tokenlist. If the dollar is a new token, add apps/web/public/tokens/<symbol>.svg (the CoinLogo component falls back to initials when it is missing).7
Copy
Product copy that names the dollar, the chain, the gas token or the faucet is registry-driven; brand strings are not. Check the chain’s terms of use: Robinhood’s, for instance, forbid “Robinhood” in product or token names, while “Built on Robinhood Chain” is fine.
Worked example: Robinhood Chain
Arbitrum Orbit L2 (ArbOS 61, Nitro 3.12), ETH gas, permissionless deployment, Cancun opcodes verified by execution. Both networks are in the registry withethGetLogsBlockRange: 1000 and maxLogAddresses: 60.
RPC limits: the official public RPC caps
eth_getLogs at 10,000 logs and answers 429 after a burst; thirdweb’s testnet endpoint caps 1,000 blocks and rejects server IPs without a client id; Alchemy’s free tier caps 10 blocks; dRPC’s free plan caps 100 blocks but is the only public archive endpoint. Use an Alchemy or QuickNode key for PONDER_RPC_URL_<chainId> (a paid endpoint for mainnet) and keep MAX_REQUESTS_PER_SECOND low on the public one.