Developer Docs
Everything you need to launch, trade and build on Robin Labs Pad — a creator-first memecoin launchpad on Robinhood Chain. One-transaction launches into a real Uniswap v3 pool, a bonding-curve, a “let it ride” graduation, and a permanently-locked floor: the Bond.
01 · Start hereOverview
Robin Labs is a set of audited, non-upgradeable contracts. There are no proxies and no admin backdoors — the platform owner can point new launches at a fee wallet and nothing else. A launch is a single transaction that deploys the token, seeds the bonding curve, opens trading, and (optionally) executes the creator's own opening buy — atomically.
- Real DEX from block one. Every coin is a genuine Uniswap v3 pool, so it's chartable on DexScreener the moment it launches.
- Approval-free buys. Buying sends native ETH — no token approval. Selling needs one exact-amount approval to the router (never infinite, never to a personal wallet).
- Fees ride the protocol. The 1% is the Uniswap LP fee tier, collected in-protocol — there's never a side-transfer bolted onto your transaction.
- Un-ruggable graduation. At graduation, liquidity is posted to the Bond and locked forever, with a WETH floor that only deepens with volume.
01 · Start hereNetwork & addresses
| Key | Value |
|---|---|
| Chain | Robinhood Chain (Arbitrum Orbit L2, EVM) |
| Chain ID | 4663 (0x1237) |
| Currency | ETH (18 decimals) |
| Public RPC | https://robinhoodchain.blockscout.com/api/eth-rpc |
| Explorer | https://robinhoodchain.blockscout.com |
| Per-tx gas cap | 16,777,216 (2²⁴) — relevant if you batch calls |
Contract addresses (live)
| Contract | Address | Role |
|---|---|---|
| CurvePadFactory | 0x44855d49E73Ad103Df51871A072FEe8709E6A2d6 | One-call launch entrypoint |
| PadRouter | 0xAEFE708e04D3E2e9609e6bC987903b31818C2a46 | The swap desk — every buy/sell goes through it |
| WETH | 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73 | Canonical wrapped ETH |
| UniswapV3Factory | 0x1f7d7550b1b028f7571e69a784071f0205fd2efa | The real v3 factory each pool is created on |
CurvePool and Bond addresses are per-coin — you get them from the factory's Launched event or recordOf(token), and from router.bondOf(token).
01 · Start hereArchitecture
A coin's whole life touches four contracts:
| Contract | Owns |
|---|---|
| CurvePadFactory | Deploys the token + curve + pool in one tx, registers the coin with the router, runs the anti-snipe opening buy. |
| CurvePool | The bonding curve — a single-sided v3 position spanning [startTick → gradTick]. Owns graduation and the “let it ride” logic. |
| PadRouter | The only trade path. Applies the 1% fee in-protocol, splits it to escrows, exposes dev fee controls. |
| Bond | Protocol-owned floor posted at graduation and locked forever — Sherwood (full-range LP), Bounty (WETH buy-wall), Ambush (token sell-wall). Fees compound back in via poke(). |
02 · Contracts & ABICurvePadFactory
The launch entrypoint. launch() is payable — any ETH you send is the creator's own opening buy (capped at 2% of supply), executed atomically before public trading opens.
// The launch params tuple. tax.projectWallet receives the creator's sell fee.
function launch(
(string name, string symbol, address dev,
(uint16 buyBps, uint16 sellBps, uint16 walletBps,
uint16 floorBps, uint16 burnBps, address projectWallet) tax) p
) payable returns (address token, address curve, address pool)
function tokenCount() view returns (uint256)
function allTokens(uint256 index) view returns (address)
function recordOf(address token) view returns (address token, address curve, address dev, uint256 at)
event Launched(address indexed token, address indexed curve, address indexed pool, address dev, uint256 devBought)02 · Contracts & ABIPadRouter
Every trade goes through the router. Buys send native ETH (no approval); sells need one exact-amount approval to the router. The fee split happens inside — no side transfers.
function buy(address token, uint256 minOut) payable returns (uint256 tokensOut) function sell(address token, uint256 amountIn, uint256 minOutEth) returns (uint256 ethOut) // reads function configOf(address token) view returns ( (address pool, address curve, address projectWallet, uint16 buyBps, uint16 sellBps, uint16 walletBps, uint16 floorBps, uint16 burnBps, bool set) ) function devEscrow(address token) view returns (uint256) // creator's uncollected sell fees (wei) function bondOf(address token) view returns (address) // creator-only fee controls (projectWallet) function withdrawDev(address token) // collect escrowed sell fees to the wallet function burnDev(address token) // buy + burn with them instead event Bought(address indexed token, address indexed buyer, uint256 ethIn, uint256 fee, uint256 tokensOut) event Sold(address indexed token, address indexed seller, uint256 tokensIn, uint256 fee, uint256 ethOut) event FeeSplit(address indexed token, uint256 platform, uint256 deferred, uint256 platformCut, uint256 dev, uint256 floor, uint256 burn)
02 · Contracts & ABICurvePool
The bonding curve and graduation. Read it for progress and the graduation window; call graduate() (permissionless) to post the Bond, or setGradTarget() (creator-only) to move the auto-graduate price.
function pool() view returns (address) // the Uniswap v3 pool function dev() view returns (address) function bond() view returns (address) // zero until graduated function seeded() view returns (bool) function graduated() view returns (bool) function ready() view returns (bool) // eligible to graduate right now function seedTime() view returns (uint64) // geometry — ticks along the curve (price rises left→right) function startTick() view returns (int24) // curve start (~$4k FDV) function minGradTick() view returns (int24) // earliest graduation (~$30k) function gradTarget() view returns (int24) // auto-graduate price (dev-settable) function gradTick() view returns (int24) // ceiling (~$76k) function setGradTarget(int24 targetTick) // creator only, within [min, ceiling] function graduate() // permissionless once ready() event Seeded(int24 curveLo, int24 curveHi, uint128 liquidity) event GradTargetSet(int24 targetTick) event Graduated(address indexed bond, uint256 raisedWeth, uint256 leftoverToken)
02 · Contracts & ABIBond
The floor, posted once at graduation and locked forever. Anyone can call poke() to sweep the Sherwood LP's accrued Uniswap fees and compound them back into the locked position — fees never leave to a wallet.
function poke() // permissionless: compound Sherwood LP fees back into the floor
event Posted(uint128 sherwoodL, uint128 bountyL, uint128 ambushL)
event Poked(int24 tick, uint128 bountyL, uint128 ambushL, uint256 sherwoodFees0, uint256 sherwoodFees1)02 · Contracts & ABIEvents reference
These are everything the indexer consumes — enough to reconstruct the full state of the pad.
| Event | Emitter | Meaning |
|---|---|---|
| Launched | Factory | New coin: token, curve, pool, dev, opening buy |
| Bought | Router | A buy: ETH in, fee, tokens out |
| Sold | Router | A sell: tokens in, fee, ETH out |
| FeeSplit | Router | Exact fee routing per trade (platform/deferred/cut/dev/floor/burn) |
| GradTargetSet | Curve | Creator moved the auto-graduate price |
| Graduated | Curve | Graduation: raised WETH, the Bond address |
| Posted / Poked | Bond | Floor posted / fees compounded |
03 · IntegrateBuild a bot
Everything here is permissionless and public — no API key, no allow-list, no sign-up. If you can send a transaction, you can integrate. Three calls get you a working trade bot: watch launches, buy, sell.
// 1) WATCH new launches — one event on the factory const factory = new ethers.Contract(FACTORY, [ "event Launched(address indexed token,address indexed curve,address indexed pool,address dev,uint256 devBought)", ], provider); factory.on("Launched", (token, curve, pool, dev) => { // ...decide whether to snipe it, inside the same block the dev opens }); // 2) BUY — native ETH in, no approval const value = ethers.parseEther("0.1"); const q = await router.buy.staticCall(token, 0n, { value }); await (await router.buy(token, q * 99n / 100n, { value })).wait(); // 3) SELL — one exact-amount approval, then sell await (await erc20.approve(ROUTER, amountIn)).wait(); await (await router.sell(token, amountIn, minOutEth)).wait();
Ideas that print: snipe bot (buy on Launched) · buy-alert / trending bot (poll the API → Telegram/X) · keeper (graduate() is permissionless — fire it when ready() flips) · copy-trade (mirror a wallet's Bought/Sold). Nothing to request, no rate limit on-chain — and every trade your bot routes still pays the coin's fee in-protocol, so the floor and the whole ecosystem grow with your volume. Bring the bots.
03 · IntegrateLaunch a coin
One transaction. Send ETH with the call to make the creator's opening buy (≤2%), or send 0 for a clean launch. All snippets use ethers v6.
import { ethers } from "ethers"; const FACTORY = "0x44855d49E73Ad103Df51871A072FEe8709E6A2d6"; const abi = [ "function launch((string name,string symbol,address dev,(uint16 buyBps,uint16 sellBps,uint16 walletBps,uint16 floorBps,uint16 burnBps,address projectWallet) tax) p) payable returns (address token,address curve,address pool)", ]; const signer = await new ethers.BrowserProvider(window.ethereum).getSigner(); const factory = new ethers.Contract(FACTORY, abi, signer); const me = await signer.getAddress(); const params = { name: "Sherwood", symbol: "WOOD", dev: me, tax: { buyBps: 100, // 1% buy → platform (min) sellBps: 100, // 1% sell → you, the creator (min) walletBps: 0, floorBps: 0, burnBps: 0, // split of any ABOVE-1% fee projectWallet: me, // where your sell fee lands }, }; // staticCall first to get addresses without spending gas, then send. const [token] = await factory.launch.staticCall(params, { value: 0n }); const tx = await factory.launch(params, { value: ethers.parseEther("0.02") }); // opening buy await tx.wait(); console.log("launched", token);
03 · IntegrateBuy & sell
const ROUTER = "0xAEFE708e04D3E2e9609e6bC987903b31818C2a46"; const rAbi = [ "function buy(address token,uint256 minOut) payable returns (uint256)", "function sell(address token,uint256 amountIn,uint256 minOutEth) returns (uint256)", ]; const router = new ethers.Contract(ROUTER, rAbi, signer); // BUY — native ETH in, no approval. Quote first, then apply slippage. const quoted = await router.buy.staticCall(token, 0n, { value: ethers.parseEther("0.1") }); const minOut = quoted * 99n / 100n; // 1% slippage await (await router.buy(token, minOut, { value: ethers.parseEther("0.1") })).wait(); // SELL — one EXACT-amount approval to the router, then sell. const erc20 = new ethers.Contract(token, ["function approve(address,uint256) returns (bool)"], signer); await (await erc20.approve(ROUTER, amountIn)).wait(); await (await router.sell(token, amountIn, minOutEth)).wait();
03 · IntegrateRead curve state
The curve's ticks + the pool's current tick give you progress and market cap. (Or skip all of this and hit the indexer API, which precomputes it.)
const curve = new ethers.Contract(curveAddr, [ "function pool() view returns (address)", "function startTick() view returns (int24)", "function gradTick() view returns (int24)", "function graduated() view returns (bool)", ], provider); const [poolAddr, start, ceil] = await Promise.all([curve.pool(), curve.startTick(), curve.gradTick()]); const pool = new ethers.Contract(poolAddr, [ "function slot0() view returns (uint160 sqrtPriceX96,int24 tick,uint16,uint16,uint16,uint8,bool)", ], provider); const { tick } = await pool.slot0(); const span = Math.abs(Number(ceil) - Number(start)) || 1; const progress = Math.min(1, Math.abs(Number(tick) - Number(start)) / span); // 0 … 1
03 · IntegrateGraduate & dev controls
const curve = new ethers.Contract(curveAddr, [ "function ready() view returns (bool)", "function graduate()", "function setGradTarget(int24 targetTick)", ], signer); // Anyone can graduate once ready() — this is the "Graduate" button / a keeper bot. if (await curve.ready()) await (await curve.graduate()).wait(); // Creator only: move the auto-graduate price. Lower = graduate sooner; // higher = ride longer for a bigger raise + thicker floor. await (await curve.setGradTarget(targetTick)).wait(); // Creator only: collect your escrowed sell fees — or buy + burn with them. const router = new ethers.Contract(ROUTER, [ "function withdrawDev(address)", "function burnDev(address)", ], signer); await (await router.withdrawDev(token)).wait();
04 · EconomicsFee model
Every coin pays a mandatory 1% per side. A creator may set a side higher (up to 4%); the amount above 1% is the “raised” fee and splits 25% platform / 75% project.
| Flow | Goes to | Detail |
|---|---|---|
| Buy 1% base | Platform | 0.9% immediately, 0.1% released at graduation |
| Sell 1% base | Creator | Escrowed; collect to wallet or buy+burn |
| Above-1% (raised) | 25% platform / 75% project | Project 75% splits by walletBps/floorBps/burnBps |
| Graduation reward | Creator + Platform | 0.5 ETH each at graduation; the rest funds the floor |
| Sherwood LP fees | The floor | Compound back into the locked Bond via poke() |
04 · EconomicsGraduation — “let it ride”
Graduation is a window, not a line. It becomes eligible at the minimum (~$30k mcap) and can fire anywhere up to the ceiling (~$76k). The longer a coin rides, the bigger the raise and the thicker the floor.
| Parameter | Meaning | Set by |
|---|---|---|
| minGradTick | Earliest graduation is allowed (~$30k) | Fixed at launch |
| gradTarget | Auto-graduate price. Defaults 40% up the range (~$45k) | Creator (setGradTarget) |
| gradTick | Ceiling (~$76k). Buys can't push past it | Fixed at launch |
| Timeout | After 7 days, anyone may graduate at the minimum | Permissionless fallback |
On graduation the curve collects the raised WETH + unsold tokens, pays the creator 0.5 ETH and the platform 0.5 ETH (each capped at a quarter of the raise), and posts the rest as the Bond: the Sherwood full-range LP, the Bounty WETH floor, and the Ambush token wall.
05 · Build on itIndexer API
An optional read API (see /indexer in the repo) reads the events above into a database and serves a fast browse feed, trending/top sorting, search, per-coin trades and volume — so you don't fan out dozens of RPC calls per page. It's read-only and signs nothing; the pad falls back to direct-RPC when it isn't configured.
| Route | Returns |
|---|---|
| GET /health | { ok, head, cursor, coins, trades } |
| GET /api/stats | Totals: coins, graduated, 24h volume & trades |
| GET /api/coins | Browse feed — params below |
| GET /api/coin/:token | One coin, fully enriched (progress, mcap, volume) |
| GET /api/trades/:token | Recent trades (exact wei) |
# sort: new | trending | top | graduated filter: all | live | graduated GET /api/coins?sort=trending&filter=live&q=wood&limit=60 # each coin includes: { token, curve, pool, dev, name, symbol, launchTs, devBought, graduated, raisedWeth, bond, progress, mcapEth, lastPriceEth, # live snapshot — no chain read needed tradesAll, trades24h, volAllEth, vol24hEth, startTick, minGradTick, gradTick, gradTarget }
05 · Build on itSecurity model
- No proxies, no upgrades. The contracts are immutable. The platform owner (Ownable2Step) can only set the fee wallet for new launches — never touch a live coin, its curve, or the Bond.
- Floor-drain closed. Graduation refuses to post above the ceiling — the only unbacked price zone. Anywhere inside the curve, moving price up costs real WETH that joins the raise, so a manipulated graduation price is one the attacker paid for, and the floor sits below it.
- Conservation. Every wei of WETH and every token is accounted for across the lifecycle — verified to the wei by a 300-run fuzz and a random-graduation battery.
- Anti-snipe. The creator's opening buy runs atomically inside the launch tx; a CREATE2 salt with per-launch entropy blocks pre-init pool DoS.
- Fees in-protocol. The 1% is the Uniswap LP fee tier, not a side transfer — no extra instruction is ever attached to a user's transaction.