Everything about JetPad, in one place
How a launch works, where the price comes from, who gets paid, and every address and event you need to index it yourself.
Overview
JetPad is a place to launch and trade tokens on Robinhood Chain. You can browse launches, open any token to see its details, and trade straight from your wallet.
JetPad never holds your funds. Every launch and every trade is a transaction your own wallet asks you to approve, sent to a contract that cannot hold a balance between transactions.
Key facts
- Names and symbols can be copied. Always check the token address.
- Prices come from each token's own Uniswap v4 pool, from its first block.
- Every token has a fixed supply of 1,000,000,000 and 18 decimals.
- Pools hold native ETH. Nothing is ever wrapped.
- Launches can be volatile, illiquid, or lose all value.
What JetPad does not have
There is no bonding-curve phase, no migration, and no graduation. Most launchpads sell from an off-DEX curve first and move the liquidity to a real pool later; until that moment the token has no pool, so scanners cannot read it and aggregators cannot list it.
A JetPad coin skips that stage entirely. The pool is real, the liquidity is burned, and the token is tradable in the same transaction that creates it. There is no later event to wait for, and no step at which anything moves.
How launches work
Creating a launch runs one atomic transaction. It deploys the ERC-20, opens
its Uniswap v4 pool against native ETH, deposits 100% of the supply as a single-sided position,
mints the position NFT directly to 0x…dEaD, arms the 1% fee, and executes the
creator's first buy. If any part fails, none of it happened.
Token, pool and liquidity in a single transaction. The position NFT is minted straight to the burn address — it is never held, then burned; it is never held at all.
Buys and sells run against native ETH in that same pool, from the first block, and move the price. Nothing migrates, ever.
Every swap pays 1% in ETH. The creator's share accrues to their address for as long as the coin trades, and can be claimed at any time.
A single-sided position is a bonding curve
This is not an analogy. A liquidity position L over a price range
[a, b] behaves exactly like a constant product with virtual reserves:
(x + L/√b) · (y + L·√a) = L² for every price P in [a, b]
virtual ETH reserve V_e = L / √b
virtual token reserve V_t = L · √a
constant k = L²
So the curve everyone expects is there. JetPad just expresses it in Uniswap's own representation instead of a bespoke contract — which is precisely why there is nothing left to migrate afterwards, and why the pool is readable by every scanner and aggregator from the start.
The pool opens at the top of the range holding only tokens and zero ETH. Buys push the price down the range in Uniswap's orientation, which in human terms means the price in ETH per token goes up. The ETH that buyers deposit is what pays sellers — which is what makes a coin sellable from the very first trade, with no condition and nothing to unlock.
The creator's first buy
Every launch includes a buy by the creator, in the same transaction, at the floor price. It is required, and the minimum is 0.01 ETH.
The pool opens with 100% tokens and zero ETH. The creator's buy is the only ETH in it at block one. A honeypot detector buys, then tries to sell everything it just bought — and a pool too shallow to pay that sell back reverts, which the scanner correctly reports as “cannot be sold”.
0.01 ETH is the floor measured as sufficient on this chain, not an estimate. Below it, coins were flagged; at it, they are clean.
The creator buys their own tokens and can sell them back at any time. Measured round trip: 0.0105 ETH in, 0.01029 ETH out. The real cost is the 1% hook fee each way plus gas — roughly 0.0002 ETH. The rest is committed, not spent.
The cap on the first buy
The atomic first buy cannot exceed 50% of the supply
(MAX_DEV_BUY_BPS = 5000). That limit is a constant in the bytecode —
no admin can raise it, which is what makes it a guarantee rather than a policy.
It bounds the creator's privilege, not their holdings. It applies to the one
window where they buy with no possible competition, because the pool did not exist a moment
earlier. Once createCoin returns, the creator can buy more like anyone else — at
the market price, in competition with everyone, paying the 1% each time.
Never treat it as a guarantee about how the supply is distributed. Check the holders.
The opening market cap is deliberately low, and you should size that before you buy: at the
STANDARD tier it is about 2.47 ETH, so 1 ETH buys roughly 29% of the supply.
Both the ETH spent and the tokens received by the creator are published in the
CoinCreated event, and shown on every coin's page.
Trading and pricing
Every token trades against native ETH in its own Uniswap v4 pool. The price you see is the live pool price and it moves with every trade. What you actually receive can differ from the quote; slippage is how much of that movement you agree to accept.
The current pool price of one token, in ETH.
Price multiplied by the total supply.
Identical to market cap here: the supply is fixed and fully minted at launch.
How far your own trade moves the pool.
The worst execution you accept before the transaction reverts.
What the position holds around the current price — it starts as tokens and becomes ETH as people buy.
Trades are routed through JetstreamRouter, a contract with no owner, no proxy, no
pause, no sweep function, no Permit2 dependency, and no ability to hold a balance between
transactions. The JetPad interface refuses to send anything to any other target.
Launch tiers
A tier sets the price range of the launch position, and therefore the opening market cap. All three tiers share the same range width (55,800 ticks), so all three have the same ceiling — a ×265 move from the floor to the top of the range. Only the scale in ETH changes.
| Tier | Tick range | Opening market cap | Cost to buy the whole supply | Multiple |
|---|---|---|---|---|
| 0 · LOW | 152,200 → 208,000 | 0.92710 ETH | 15.0920 ETH | ×265.00 |
| 1 · STANDARD | 142,400 → 198,200 | 2.47010 ETH | 40.2101 ETH | ×265.00 |
| 2 · PREMIUM | 133,400 → 189,200 | 6.07518 ETH | 98.8963 ETH | ×265.00 |
These are the values actually reached, re-derived from the rounded ticks — never the requested bounds. Uniswap only accepts ticks on a 200 grid, so the grid moves the numbers by +0.5% to −1.1%, and the honest figure to publish is the one on chain.
The buyout cost is what lands in the pool, so it is net of the hook fee: a buyer
actually pays cost / (1 − 0.01).
The JetPad create form launches every coin at STANDARD. The other two tiers
exist on the contract and are readable through launchParams(tier) and
launchEconomics(tier), but the form does not currently expose the choice.
Fees
There is one fee: 1% of every swap, taken by JetstreamHook on the
ETH leg. It is always paid in ETH, never in the memecoin, from the very first trade.
The pool's own LP fee is zero. The hook is the only source of fees in the system, which is what lets the liquidity position be burned and still produce revenue — the fee belongs to the swap, not to whoever holds the liquidity.
How the 1% is split
feeBps, devBps and buybackBps are written into
configOf[poolId] when the pool is registered, and read from there forever after.
The owner cannot change the fee or the split of a coin that already exists.
Only the destination wallets are read live, so that a compromised address can be replaced. The shares themselves cannot be.
The fee rate is capped at 300 bps by a constant in both the
factory and the hook. It is 100 bps today. There is no creation fee:
creationFee is 0.
Creator rewards
Fees accumulate per pool as pendingEth[poolId], held as ERC-6909 claims on the
Uniswap PoolManager. Turning them into real ETH takes two permissionless steps:
// 1. Split what has accrued. Anyone can call this, for any number of pools at once.
// The proceeds are credited to the beneficiaries, never to the caller.
hook.harvest(bytes32[] poolIds)
// 2. Withdraw your own balance. address(0) means native ETH.
hook.claim(0x0000000000000000000000000000000000000000)
Both are available from the profile panel in the JetPad interface, which shows each of your coins, its market cap, and what it currently has waiting.
The creator role can be handed over with a two-step transfer —
transferCreator(poolId, to) then acceptCreator(poolId) from the new
address. It moves the fee stream and nothing else: it grants no power over the liquidity, which
is burned, or over trading.
What is guaranteed
These are properties of deployed bytecode, each one verifiable by anyone without trusting JetPad.
| Property | How to check it |
|---|---|
| Liquidity is burned | The position NFT is minted directly to 0x…dEaD. Call ownerOf(positionTokenId) on the Uniswap PositionManager. |
| The token has no owner | owner() is a pure function returning the zero address. There is no storage behind it, and no transferOwnership. |
| No mint after deployment | The entire supply is minted once, in the constructor. There is no mint path. |
| No transfer can be blocked | _update is not overridden. No pause, no blacklist, no cooldown, no max-wallet — nothing that could make a transfer fail beyond ERC-20's own rules. |
| Positions stay withdrawable | The hook holds no remove-liquidity permission bits. Even if its swap path ever broke, every position could still be withdrawn. |
| Pausing cannot trap funds | The factory's pause freezes createCoin only. Swaps live in the PoolManager and fees in the hook; neither consults it. |
| Fees are pull, never push | Nothing is ever pushed to a beneficiary. Balances are claimed by their owner. |
Risk disclosures
Tokens launched through JetPad are user-created and experimental. Before signing, review the token address, the creator, the liquidity, the holder concentration and the transaction preview.
- Prices can move quickly and liquidity can be thin.
- Similar names and images can represent completely unrelated tokens.
- A creator's first buy can be as large as half the supply. Check who holds what.
- Smart contracts, wallets, RPCs and indexers can fail.
- Displayed values are estimates, not execution guarantees.
- The contracts have not been reviewed by an external auditor.
JetPad is an interface. It is not investment advice, and it is not a statement about any token's quality.
Network
A small, verifiable integration surface. Everything reads off the contracts — index the factory and the pool events and you have a trust-minimised source of truth that does not depend on JetPad being up.
| Property | Value |
|---|---|
| Network | Robinhood Chain (Arbitrum Nitro) |
| Chain ID | 4663 · 0x1237 |
| Native asset | ETH |
| Public RPC | https://rpc.mainnet.chain.robinhood.com |
| Explorer | robinhoodchain.blockscout.com |
| Block time | ~0.10 s |
| DEX | Uniswap v4, native ETH, custom hook |
| Pool LP fee | 0 — the hook is the only fee |
| Tick spacing | 200 |
| Supply | 1,000,000,000 (1e9 × 1e18) |
| Creation fee | 0 |
| Minimum creator buy | 0.01 ETH |
-
block.numberreturns the L1 block number and only advances every ~12 s. Never use it as a clock.block.timestampandArbSys.arbBlockNumber()track L2. -
eth_getLogserrors above its cap rather than truncating — good — but the observed cap does not match the announced one. Do not hardcode a range: split adaptively, driven by the error.
Contracts
Deployed addresses on Robinhood Chain. Contracts are immutable: a new version ships as new addresses, listed here.
The hook's factory is immutable and its address is CREATE2-mined to carry
exactly the permission bits 0x08CC in its low 14 bits. Changing either contract
changes the mined address, so they are always deployed as a pair. If you see one of them
change, expect the other to have changed too.
Hostile addresses
At the addresses Uniswap uses on Ethereum and every other chain, this chain hosts an
unrelated contract whose fallback forwards msg.value to a third
party. They are not a stale deployment to be corrected — sending ETH to them is a
loss of funds.
| Address | What it is elsewhere |
|---|---|
| 0x1F98431c…F984 | UniswapV3Factory — drainer here |
| 0xC36442b4…FE88 | NonfungiblePositionManager — drainer here |
| 0xE592427A…1564 | SwapRouter — drainer here |
| 0x61fFE014…B21e | QuoterV2 — drainer here |
| 0x6fF5693b…9b43 | Real UniversalRouter bytecode, every immutable dangling |
| 0x88767899…0904 | UniversalRouter with a proven bytecode modification |
JetPad refuses these addresses in two independent places — in the browser before signing, and in the API before it will name any call target at all. Duplicating that check is deliberate: this is the one class of mistake that cannot be undone.
Onchain events
Index CoinCreated on the factory, then the PoolManager's Swap events
filtered by each poolId. Onchain events are the authoritative source of truth, and
no eth_call is needed: CoinCreated carries the entire
launch position.
event CoinCreated(
address indexed token,
address indexed creator,
bytes32 indexed poolId,
string name,
string symbol,
string tokenURI, // IPFS CID
uint256 totalSupply, // always 1e27
uint256 positionTokenId, // NFT minted to 0x…dEaD — the burn proof
uint160 sqrtPriceX96, // opening price, exactly sqrt(tickUpper)
uint128 liquidity,
int24 tickLower,
int24 tickUpper,
uint8 tier, // 0 LOW · 1 STANDARD · 2 PREMIUM
uint16 feeBps, // frozen for this pool (100 = 1%)
uint256 devBuyEth, // ETH the creator's first buy actually spent
uint256 devBuyTokens, // tokens they received — display this
uint16 implVersion // 3 = single-sided launch
);
// topic0
0xef85cf514fdefb3937035e5e5f9200299d6354dae086a76b9271b5e363ebab07
// Written once per coin, by the factory, during creation.
event PoolRegistered(bytes32 indexed poolId, address indexed token, address indexed creator, uint16 feeBps);
// Emitted on EVERY swap. This is the coin's revenue, with no state read at all.
// `takenBeforeSwap` says which leg paid; the amount is always in wei of ETH.
event HookFeeAccrued(bytes32 indexed poolId, uint256 amount, bool takenBeforeSwap);
// A treasury movement, not new revenue. Do not double-count it against the above.
event HookFeesHarvested(bytes32 indexed poolId, uint256 amount);
event CreatorTransferStarted(bytes32 indexed poolId, address indexed from, address indexed to);
event CreatorTransferred(bytes32 indexed poolId, address indexed from, address indexed to);
// role: 0 = DEV · 1 = BUYBACK · 2 = PLATFORM. asset(0) = native ETH.
event FeesAccrued(address indexed account, address indexed asset, uint256 amount, uint8 role);
event FeesClaimed(address indexed account, address indexed asset, uint256 amount);
The PoolKey, and deriving the poolId
A v4 pool has no address of its own. It is identified by the hash of its key, and every JetPad pool has the same shape:
| Field | Value |
|---|---|
| currency0 | 0x0000000000000000000000000000000000000000 — native ETH, always sorts first |
| currency1 | the coin, always |
| fee | 0 |
| tickSpacing | 200 |
| hooks | the JetstreamHook address |
fee is 0, not 3000 or 10000. Quoting or simulating a JetPad
pool with a standard tier reverts PoolNotInitialized() — which is a tooling
mistake, and says nothing whatsoever about the coin.
import { createPublicClient, http, parseAbiItem } from "viem";
const client = createPublicClient({
chain: {
id: 4663,
name: "Robinhood Chain",
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
rpcUrls: { default: { http: ["https://rpc.mainnet.chain.robinhood.com"] } },
},
transport: http(),
});
const launches = await client.getLogs({
address: "0x4c0cdfB2cb5D38F58e20152C7B9dCFb39019A52f",
event: parseAbiItem(
"event CoinCreated(address indexed token, address indexed creator, bytes32 indexed poolId, string name, string symbol, string tokenURI, uint256 totalSupply, uint256 positionTokenId, uint160 sqrtPriceX96, uint128 liquidity, int24 tickLower, int24 tickUpper, uint8 tier, uint16 feeBps, uint256 devBuyEth, uint256 devBuyTokens, uint16 implVersion)",
),
fromBlock: 23628017n, // the factory's first block — earlier is wasted work
toBlock: "latest",
});
Nothing replaces the Migrated event other launchpads emit — a JetPad coin is in
its final state from CoinCreated onward. An indexer waiting for a transition
should be simplified, not adapted. Deduplicate on (txHash, logIndex).
Reading token state
Every launch token is self-describing on chain, and the factory answers everything else about the launch.
function name() view returns (string)
function symbol() view returns (string)
function decimals() view returns (uint8) // 18
function totalSupply() view returns (uint256) // 1e27, fixed
function tokenURI() view returns (string) // IPFS CID: image, description, links
function factory() view returns (address)
function owner() pure returns (address) // always 0x0 — a constant, not storage
// ⚠️ `curve()` is a legacy name kept so an external ABI does not break. It returns the
// factory, which received the supply and put all of it in the pool in the same
// transaction. It confers no power of any kind.
function curve() view returns (address)
poolIdOf(address token) returns (bytes32) // the pool's identity
poolKeyOf(address token) returns (PoolKey)
positionTokenIdOf(address token) returns (uint256) // 0 = unknown to this factory
launchParams(uint8 tier) returns (tickLower, tickUpper, sqrtPriceX96Init, liquidity)
launchEconomics(uint8 tier) returns (startingMarketCapWei, fullBuyoutCostWei, finalMarketCapWei)
coinCount() returns (uint256)
feeBps() devBps() buybackBps() // the CURRENT defaults for NEW coins
configOf(bytes32 poolId) returns (set, creator, feeBps, devBps, buybackBps)
feeBpsOf(bytes32 poolId) returns (uint16) // 0 = not a JetPad pool
creatorOf(bytes32 poolId) returns (address)
pendingEth(bytes32 poolId) returns (uint256) // accrued, not yet harvested
// selectors, if you are building calldata by hand
// pendingEth(bytes32) 0x4943253a
// harvest(bytes32[]) 0x13df2c7a
// devBps() 0x78b2c179
To verify the burn — the one check worth doing on any coin — take
positionTokenId from CoinCreated and call
ownerOf(positionTokenId) on the Uniswap PositionManager. It returns
0x…dEaD, and it does so from the coin's very first block.
Pricing
The launch event carries enough to rebuild the whole curve off chain, with no RPC call. Prices
after that come from the PoolManager's Swap events on the coin's
poolId.
// currency0 is native ETH, so Uniswap's P is TOKENS per ETH.
// Human price (ETH per token) is 1/P — it goes UP as people buy.
ratio = sqrtPriceX96 / 2**96
tokensPerEth = ratio * ratio
ethPerToken = 1 / tokensPerEth
marketCapWei = totalSupply / tokensPerEth
// The equivalent virtual reserves, if you prefer curve terms:
sqrtA = sqrtPriceX96AtTick(tickLower)
sqrtB = sqrtPriceX96 // opening price IS the upper bound
virtualEthWei = liquidity / sqrtB
virtualTokens = liquidity * sqrtA
k = liquidity ** 2
// ETH needed to buy the entire supply, net of the 1% hook fee:
fullBuyoutWei = liquidity * (1/sqrtA - 1/sqrtB)
k = V_e × (S + V_t), not V_e × V_t. The
y in the identity is the position's live balance — zero at launch, the
full supply once everything has been sold — not a countdown from the supply. Getting this
wrong is off by a factor of about 16.3 at the current calibration.
For USD figures, multiply by any ETH/USD source. The JetPad interface uses a spot feed and applies it to the ETH-denominated numbers; it never derives a USD price on chain.
Public API
A read API sits in front of the indexer for convenience — charts, search, quotes. It is a convenience layer over the chain, never an authority: everything it returns is derived from the events above, and anything that matters should be verified against them.
https://api-production-ecec.up.railway.app
| Endpoint | What it returns |
|---|---|
GET /coins | The listing. sort, limit, q, creator, status. |
GET /coins/:address | One coin: metadata, pool state, market cap, last trade. |
GET /coins/:address/trades | Trade history, newest first. |
GET /coins/:address/candles | OHLCV. Intervals down to 1s — the chain produces ten blocks a second. |
GET /quote/:address | A priced buy or sell, plus ready-to-sign calldata and its target. |
GET /quote/:address/state | Live pool state behind a quote. |
GET /fees/:devAddress | What a creator has accrued and can claim. |
GET /launch/params | Tier calibration and the current minimum creator buy. |
POST /launch/calldata | Encoded createCoin calldata. |
POST /metadata | Pins an image and its metadata to IPFS, returns the CID. |
GET /health | Database, cache, pinning and indexer lag. |
A WebSocket on the same host pushes new coins, trades and candle updates as they are indexed. The interface uses it instead of polling, because at 100 ms blocks polling is always behind.
/quote returns a call target and calldata. The API checks that the PoolKey it is
about to encode hashes to the coin's own poolId before naming any address at
all, and the JetPad browser client independently re-checks that the target is not a known
decoy, that the approval spender is that same target, and that the calldata decodes to the
numbers on screen. If you build your own client, do the same.
Support
If you are indexing launches, deriving prices, wiring trades or verifying onchain state, reach out and we will help you get it right.
Versioning
Deployed contracts are immutable. New versions ship as new factory and hook addresses, listed
under Contracts. implVersion in
CoinCreated tells you which launch mechanism produced a given coin — 3
is the single-sided launch described here.
Terms and attribution
Onchain data is public and free to read. You are responsible for what you do with it. JetPad is provided as is, without warranties, and we are not liable for losses arising from integrations, interfaces, RPCs or indexers.
- Do not present third-party services as operated by JetPad.
- Do not use the JetPad name or marks in a way that misleads users.
- Availability of the interface and of public infrastructure is not guaranteed.
