For devsFor developers
For developers
Start here
A coin lives in two phases. Pre-bond it sells on the bonding curve, a contract you call directly. Post-bond its raise and reserved supply sit in a Uniswap v4 pool whose position is burned, and it trades through the Universal Router like any v4 pool - with one fee hook you must respect. This page is the shortest path through both; the full protocol reference is /docs and the client library is /sdk.
- Trading is open and non-custodial. The platform never signs, relays or gates a trade. Your wallet calls the curve pre-bond and the router post-bond; the API is discovery and metadata only, and even that has an on-chain substitute (the event feed below).
- Every amount is in the coin's quote asset, in base units. On a native-quoted coin that is USDC x 10^18 - the native gas token here is USDC, so a 6500e18 bonding target is a $6,500 raise. A coin quoted in an approved ERC-20 uses that token's own decimals.
- Dispatch on the coin, never on the config. A coin trades on the curve that launched it forever; a graduated pool bakes its hook into its PoolKey. Take
providerMeta.curveAddressandproviderMeta.hookAddressfrom the coin's own row.curveContracts.bondingCurveV4names where NEW launches land, which after the next release will differ from where existing coins live.
Test against production with small amounts
Chain access
| Network | Arc |
|---|---|
| Chain ID | 5042 |
| CAIP-2 | eip155:5042 |
| Native token | USDC (18 decimals on the native interface) |
| Public RPC | https://rpc.mainnet.arc.io |
| Explorer | https://explorer.arc.io |
| API base | https://faze.fun/api/v1 |
| OpenAPI | https://faze.fun/openapi.json |
Bring your own RPC: every quote is an eth_call against a view function, so any node for chain 5042 works. The public endpoint rate-limits and caps an eth_getLogs range; use a keyed provider for anything that polls or indexes. Finality is instant: a mined receipt is final, no confirmation depth needed. Block timestamps are non-decreasing at one-second grain, which is what the hook's 2-second graduation surcharge keys on.
The PoolManager on Arc is the canonical Uniswap deployment, shared with every other v4 pool on the chain: filter Swap logs by PoolId, never scan the manager - a chain-wide topic scan blows the RPC's result cap.
Addresses
Take these from GET /launchpad/config -> curveContracts at runtime. The table exists so you can recognize what you read back, not so you can hardcode it - a deployment can move a contract, and a stale address builds a perfectly valid transaction aimed at the wrong one. The PoolManager is not in the served config today; it is listed here from the committed chain profile.
| Curve release | 9.0 |
|---|---|
| BondingCurveV4 (pre-bond venue) | 0x6A62919ccbf0c19e0C4e084F986b582b4492dDA4 |
| LaunchpadHook (pool fee hook) | 0x47e7936ae9891e61C5123db720593c05dE7120cc |
| UniswapV4Migrator | 0x7c8dE42426A058B778DCe8530537cd62eF0178C4 |
| Universal Router (post-bond venue) | 0x4fcA4a51Ab4F23A7447b3284fBd7D73289A89Fb1 |
| V4Quoter | 0x8Dc178eFB8111BB0973Dd9d722ebeFF267c98F94 |
| StateView | 0xF3334192D15450CdD385c8B70e03f9A6bD9E673b |
| Permit2 | 0x000000000022D473030F116dDEE9F6B43aC78BA3 |
| Uniswap v4 PoolManager (Swap logs) | 0x8366a39CC670B4001A1121B8F6A443A643e40951 |
| Uniswap v4 PositionManager | 0x6049c9a0e26405C0985f9E3685C87d0aE917f82B |
Live dials
The switches and dials an operator can move. Read live from the deployment's config when it resolves; where it does not, the row names the contract read that answers instead.
| Curve trade fee | 1% |
|---|---|
| Sniper-tax window | 3 seconds from a coin opening (99% decaying to the base fee) |
| Raise band | $6,500 - $15,500 (5 stops) |
| Migration fee | 0% |
| Graduation surcharge | ON - 20% both directions for the first 2 seconds after graduation |
| Post-graduation sell window | off |
| Post-graduation buy window | off |
| Quote assets | 1 approved (a coin's providerMeta.quoteToken says which) |
| Pool base fee | per coin - providerMeta.poolFeeBps, chosen at launch from the menu |
Discovery
Public reads
Base path https://faze.fun/api/v1. All GETs, anonymous, JSON, amounts as base-unit decimal strings (convert with BigInt, never floating point). The full surface is openapi.json.
| GET /launchpad/config | curveContracts, quoteAssets, sniperTaxWindowSeconds, raiseLadder |
|---|---|
| GET /launchpad/launches | keyset list; state=<lifecycle>, sort=recency|momentum, search=, cursor= |
| GET /launchpad/launches/:mint | one coin: lifecycleState, bondingTarget, curveProgress, providerMeta |
| GET /launchpad/tokenlist.json | Uniswap-standard list: curve + graduated coins, routing extensions |
| GET /launchpad/tokenlist-graduated.json | graduated only; every entry carries the full poolKey |
| GET /launchpad/coins/:mint/trades | the tape (also candles, holders, metrics, traders) |
| GET /launchpad/wallets/:wallet/holdings | a wallet's positions (also trades, pnl) |
The launch record's providerMeta is the per-coin routing block: curveAddress, curveRelease, hookAddress, quoteToken (null = native), poolFeeBps and, once graduated, graduatedPoolId. Note that graduatedPoolAddress is the HOOK address, not a pool - a v4 pool has no address.
The token lists carry the same facts under extensions (venue, curve, curveRelease, quoteToken as the zero address for native, hook, poolKey). They refresh every few minutes, drop coins with no trade in 7 days, and are the cheapest polling surface for "what is tradable right now".
Lifecycle to venue
lifecycleState on the launch record (the list filter is state=) decides the venue:
| curve-trading, dormant | curve - buy and sell on BondingCurveV4 |
|---|---|
| awaiting-dev-buy | curve, closed - only the creator's reserved first buy is accepted |
| graduating | none - wait one block and re-read |
| graduated | pool - swap through the Universal Router |
| abandoned | curve, SELL ONLY - buy reverts CoinAbandoned |
| launched, launch-failed | not tradable |
The buy that empties the curve graduates the coin INSIDE the same transaction: from the next block the venue is the pool. Re-resolve on every CurveComplete revert, on every Completed / Graduated log, or by polling lifecycleState.
Pre-bond
Trading on the curve
struct BuyQuote { uint256 tokensOut; uint256 ethUsed; uint256 tradeFee; bool completes; }
function getCoin(address token) external view returns (Coin memory);
function quoteBuyFor(address token, address buyer, uint256 ethGross) external view returns (BuyQuote memory);
function quoteSell(address token, uint256 tokensIn) external view returns (uint256 ethOut, uint256 ethGross, uint256 fee);
function buy(address token, uint256 quoteIn, uint256 minTokensOut) external payable returns (uint256 tokensOut);
function sell(address token, uint256 tokensIn, uint256 minEthOut) external returns (uint256 ethOut);- Read the coin.
getCoin(token)on the coin's curve.activefalse is the dev-buy gate,completetrue means the sale is over,abandonedtrue means sell-only. Spot price is(ethOffset + ethReserve) / (TOKEN_OFFSET + tokenReserve)in quote per base unit. - Quote the buy for the wallet that signs.
quoteBuyFor(token, buyer, quoteGross)returns a STRUCT (it ABI-encodes as a 4-tuple). While a coin's sniper-tax window is open, a buy from a wallet the launch did not exempt pays a fee that starts at 99% and decays linearly to the base fee - so a quote for the zero address is the worst case, not yours.ethUsed < quoteGrossonly when this buy completes the sale; the remainder is refunded in-transaction. - Buy.
buy(token, quoteIn, minTokensOut)withmsg.value == quoteInexactly on a native-quoted coin (approve the quote asset for the curve and send no value on an ERC-20-quoted one). One transaction, no approval. - Sell.
quoteSell(token, tokensIn)returns the net out, thenERC20.approve(curve, tokensIn)for the exact amount andsell(token, tokensIn, minEthOut). Proceeds arrive in the coin's quote asset. Sells never pay the sniper tax. - Reverts to map:
SlippageExceeded,CurveComplete(you raced the completing buy - flip to the pool),CoinAbandoned,CurveNotActive(dev-buy gate),UnknownCoin(wrong curve),AmountTooSmall,NativeValueMismatch.
The curve is a virtual-reserve constant product: 7/9 of the supply sells on the curve, 2/9 is reserved for the pool, and the coin opens at 18/49 of the raise as fully-diluted value and closes at 4.5x it. The full derivation, the Coin struct and the LaunchTerms tuple are in the protocol docs.
Post-bond
Trading in the pool
Every graduated coin lands in a hooked Uniswap v4 pool. A v4 pool has no address - it is a PoolKey entry in the PoolManager singleton - and every Faze pool has the same committed shape:
PoolKey {
currency0: <the lower of the two addresses: the coin's quote asset or the coin>
currency1: <the higher of the two>
fee: 0 // the LP fee is ZERO - the whole fee lives in the hook
tickSpacing: 200
hooks: <the coin's stamped hook address>
}
// PoolId = keccak256(abi.encode(key)) - check it against providerMeta.graduatedPoolId- Orientation is a per-coin fact. Uniswap sorts the pair by address. A native-quoted coin always has native (
address(0)) ascurrency0; an ERC-20-quoted coin can land on either side. Take the key verbatim fromtokenlist-graduated.json->extensions.poolKeyand check its hash againstproviderMeta.graduatedPoolId. - Quote through V4Quoter (
quoteExactInputSinglewith the key,zeroForOnetrue for a buy on a native-quoted coin,hookData: 0x). The quoter executes the hook, so the result already nets the fee. Never price offslot0or reserves alone: the LP fee is 0 and the whole fee lives in the hook. - Buy (native-quoted):
UniversalRouter.execute(commands, inputs, deadline)with commandV4_SWAP (0x10)and actionsSWAP_EXACT_IN_SINGLE (0x06),SETTLE_ALL (0x0c),TAKE_ALL (0x0f); the quote rides asmsg.value. One transaction, no approvals. - The swap parameters differ by router build. The newer Universal Router build decodes
SWAP_EXACT_IN_SINGLEas six fields -(poolKey, zeroForOne, amountIn, amountOutMinimum, minHopPriceX36, hookData)- and the older one (thev4-periphery1.0.3 interface on npm) as five, withoutminHopPriceX36. Which build a chain runs is a property of its deployment: only the newer one's bytecode contains the selector0x4713c18b. The wrong shape still works on a native-quoted pool and reverts with empty data on every pool whosecurrency0is a real address. One layout decodes on both: six fields withminHopPriceX36 = 0x140and emptyhookData. Simulate your calldata against the deployed router, on an ERC-20-quoted pool, before you ship it. - Sell: two approvals, then the same execute.
ERC20.approve(permit2, amount), thenPermit2.approve(coin, universalRouter, amount, expiry)with expiry = your swap deadline, then the swap. Broadcast in order and wait for each receipt - a swap mined before its approvals reverts. The same two legs apply to the QUOTE asset when buying an ERC-20-quoted coin. - Settlement must cover swap plus fee. The hook takes the entire fee via beforeSwap/afterSwap return deltas, in the quote asset only. Open-delta settlement (
SETTLE_ALL/TAKE_ALL) handles it; a hand-rolledunlockmust settle the full owed amount, not the pool-math amount.
The fee, live
function quoteFees(PoolId poolId) external view
returns (uint16 buyFeeBps, uint16 sellFeeBps, uint64 buyWindowEndsAt, uint64 sellWindowEndsAt);
function currentBuyFeeBps(PoolId poolId) external view returns (uint16);
function currentSellFeeBps(PoolId poolId) external view returns (uint16);The rate is per pool, differs per side and moves with time: the pool's base fee, an optional decaying sell window and buy window the creator opted into at launch, and a flat 20% surcharge on both sides for the first 2 seconds after graduation while the operator switch is on. Do not compute any of it yourself - quoteFees(poolId) is one call, or quote through V4Quoter, which executes the hook and needs none of this. A bot that sells into the graduation block pays the surcharge; waiting 2 seconds pays the base fee.
Spot for display: StateView.getSlot0(poolId). With the quote as currency0 the sqrtPrice reads coin-per-quote, so invert for a quote-per-coin price. The graduation position itself is minted through Uniswap's PositionManager to the dead address and can never be pulled - the protocol docs carry the reads that prove it.
Shortcuts and traps
The SDK does all of this
@fazedotfun/sdk ships the exact quote and build path the Faze web app runs, against an RPC you choose. viem is a peer dependency.
import { createClient } from '@fazedotfun/sdk';
import { createTrader } from '@fazedotfun/sdk/chain';
const client = createClient({ baseUrl: 'https://faze.fun/api/v1' });
const trader = createTrader({
client,
privateKey: process.env.PRIVATE_KEY,
rpcUrl: process.env.RPC_URL, // your own endpoint - nothing here goes through the platform
});
// 1 USDC in - on a native-quoted coin. A coin with a providerMeta.quoteToken is bought in THAT asset's base units.
// The trader picks curve vs pool off the coin's lifecycle and quotes for its own address.
const quote = await trader.quote({ mint, side: 'buy', amountIn: 1_000_000_000_000_000_000n });
const result = await trader.trade({ mint, side: 'buy', amountIn: 1_000_000_000_000_000_000n, slippageBps: 100 });
result.status; // 'confirmed' | 'reverted' - what the receipt said
result.hashes; // every hash broadcast, in order; the last one is the tradeIf the bot signs elsewhere (a per-user key store, an HSM), quoteCurveTrade / buildCurveTrade from the same /chain entry return an ORDERED txRequests list (approve legs first) for your signer to broadcast one receipt at a time. venue is 'curve' pre-bond and 'dex' post-bond. The SDK is the recommended path because it encodes every rule on this page - per-coin dispatch, quote-asset handling, exact approvals, re-quote at build, sniper-aware quoting for the signing wallet - so none can be skipped. Reference: /sdk.
ABIs
The ABI exports of the three platform contracts, produced from the source of the release this deployment serves (9.0). The Uniswap contracts (Universal Router, V4Quoter, StateView, Permit2, PoolManager, PositionManager) are the canonical Uniswap v4 builds; take their ABIs from Uniswap's universal-router, v4-periphery, permit2 and v4-core repositories.
| BondingCurveV4 | https://faze.fun/abi/BondingCurveV4.json |
|---|---|
| LaunchpadHook | https://faze.fun/abi/LaunchpadHook.json |
| UniswapV4Migrator | https://faze.fun/abi/UniswapV4Migrator.json |
Indexing without the API
// BondingCurveV4 - one eth_getLogs filter on the coin's curve address
event Launched(address indexed token, address indexed creator, LaunchTerms terms, string name, string symbol, string tokenURI);
event Bought(address indexed token, address indexed buyer, uint256 ethGross, uint256 fee, uint256 tokensOut, uint256 ethReserve, uint256 tokenReserve);
event Sold(address indexed token, address indexed seller, uint256 tokensIn, uint256 fee, uint256 ethOut, uint256 ethReserve, uint256 tokenReserve);
event Completed(address indexed token, address indexed buyer, uint256 finalRaise);
event Graduated(address indexed token, address indexed pool, address migrator, address caller, uint256 ethMigrated, uint256 migrationFee, uint256 liquidity);
event Abandoned(address indexed token, address indexed by, uint256 raise);
// LaunchpadHook - the coin -> pool edge; PoolManager.Swap filtered by PoolId is the post-bond tape
event PoolRegistered(PoolId indexed poolId, address indexed asset, address indexed creator, uint16 feeBps,
uint16 launchSellFeeBps, uint32 launchSellFeeDecay, uint16 launchBuyFeeBps, uint32 launchBuyFeeDecay,
uint16 compoundCommitBps, address quote);Launchedcarries its terms as ONE struct member that is part of the topic hash - mirror theLaunchTermstuple field-for-field (it is transcribed in the protocol docs). A coin on an earlier curve address logs its own shape; match on the topic hash per curve address.Bought/Soldeach carry the post-trade reserves, so the price after every trade is in the log itself.Graduated.poolis the hook address, not a pool. The pool handle is the PoolId;PoolRegisteredon the hook is the authoritative coin -> pool edge.
Things that bite
- Amounts are quote base units. Dollars x 10^18 on every native-quoted coin: a "0.01 ETH" default is a one-cent trade here.
- Quote for the signing wallet. Inside the sniper window a quote for the zero address is the worst case, not what an exempt wallet pays.
- Exact approvals, per trade. Approve
tokensIn(curve) oramount(Permit2) exactly; neverMaxUint256. - Ordered broadcast. Approve legs must be MINED before the trade; wait for receipts.
- The completing buy is clamped, charged only what clears the curve, and refunded in-transaction;
ethUsedin the quote tells you in advance. - 20% for 2 seconds after graduation, both sides, on the pool, while the switch is on. Read
quoteFeesor just wait. - The token list has
poolKeybut nopoolId(the schema caps extension strings at 42 characters); hash the key. - Staging is gated (401 on every route). Do not treat that as an outage.
- No third-party charts index this chain yet. Use
/launchpad/coins/:mint/candlesor your own swap indexing.
Suggested test plan
GET /launchpad/config; assertcurveContracts.chainId == 5042and activeCurveRelease == "9.0".- Pick a
curve-tradingcoin;getCoinit on itsproviderMeta.curveAddress;quoteBuyForfor your wallet with 1 USDC (1e18); buy; confirmBoughtin the receipt;quoteSellthe received amount; approve exact; sell. - Pick a graduated coin from
tokenlist-graduated.json; hash itspoolKeyand matchgraduatedPoolId; quote 1 USDC through V4Quoter; execute the buy; readquoteFees; approve through Permit2; sell back. - Watch one coin to graduation: confirm the bot flips venue on
CurveComplete/Completedwithout a restart, and does not sell inside the 2-second surcharge. - Confirm the bot refuses a buy on an
abandonedcoin before signing anything.
Universal Router (post-bond venue)