For devs

llms.txt

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.curveAddress and providerMeta.hookAddress from the coin's own row. curveContracts.bondingCurveV4 names where NEW launches land, which after the next release will differ from where existing coins live.

Test against production with small amounts

Staging runs the same code behind a privacy gate and answers 401 to every route without a gate cookie; ask us for access if you want a testnet lane. Otherwise a $1 buy on a live coin is a real end-to-end test, and a fresh graduation pool holds one raise's worth of liquidity, so anything larger just buys price impact.

Chain access

NetworkArc
Chain ID5042
CAIP-2eip155:5042
Native tokenUSDC (18 decimals on the native interface)
Public RPChttps://rpc.mainnet.arc.io
Explorerhttps://explorer.arc.io
API basehttps://faze.fun/api/v1
OpenAPIhttps://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.

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 fee1%
Sniper-tax window3 seconds from a coin opening (99% decaying to the base fee)
Raise band$6,500 - $15,500 (5 stops)
Migration fee0%
Graduation surchargeON - 20% both directions for the first 2 seconds after graduation
Post-graduation sell windowoff
Post-graduation buy windowoff
Quote assets1 approved (a coin's providerMeta.quoteToken says which)
Pool base feeper 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/configcurveContracts, quoteAssets, sniperTaxWindowSeconds, raiseLadder
GET /launchpad/launcheskeyset list; state=<lifecycle>, sort=recency|momentum, search=, cursor=
GET /launchpad/launches/:mintone coin: lifecycleState, bondingTarget, curveProgress, providerMeta
GET /launchpad/tokenlist.jsonUniswap-standard list: curve + graduated coins, routing extensions
GET /launchpad/tokenlist-graduated.jsongraduated only; every entry carries the full poolKey
GET /launchpad/coins/:mint/tradesthe tape (also candles, holders, metrics, traders)
GET /launchpad/wallets/:wallet/holdingsa 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, dormantcurve - buy and sell on BondingCurveV4
awaiting-dev-buycurve, closed - only the creator's reserved first buy is accepted
graduatingnone - wait one block and re-read
graduatedpool - swap through the Universal Router
abandonedcurve, SELL ONLY - buy reverts CoinAbandoned
launched, launch-failednot 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. active false is the dev-buy gate, complete true means the sale is over, abandoned true 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 < quoteGross only when this buy completes the sale; the remainder is refunded in-transaction.
  • Buy. buy(token, quoteIn, minTokensOut) with msg.value == quoteIn exactly 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, then ERC20.approve(curve, tokensIn) for the exact amount and sell(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)) as currency0; an ERC-20-quoted coin can land on either side. Take the key verbatim from tokenlist-graduated.json -> extensions.poolKey and check its hash against providerMeta.graduatedPoolId.
  • Quote through V4Quoter (quoteExactInputSingle with the key, zeroForOne true for a buy on a native-quoted coin, hookData: 0x). The quoter executes the hook, so the result already nets the fee. Never price off slot0 or reserves alone: the LP fee is 0 and the whole fee lives in the hook.
  • Buy (native-quoted): UniversalRouter.execute(commands, inputs, deadline) with command V4_SWAP (0x10) and actions SWAP_EXACT_IN_SINGLE (0x06), SETTLE_ALL (0x0c), TAKE_ALL (0x0f); the quote rides as msg.value. One transaction, no approvals.
  • The swap parameters differ by router build. The newer Universal Router build decodes SWAP_EXACT_IN_SINGLE as six fields - (poolKey, zeroForOne, amountIn, amountOutMinimum, minHopPriceX36, hookData) - and the older one (the v4-periphery 1.0.3 interface on npm) as five, without minHopPriceX36. Which build a chain runs is a property of its deployment: only the newer one's bytecode contains the selector 0x4713c18b. The wrong shape still works on a native-quoted pool and reverts with empty data on every pool whose currency0 is a real address. One layout decodes on both: six fields with minHopPriceX36 = 0x140 and empty hookData. 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), then Permit2.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-rolled unlock must 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 trade

If 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.

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);
  • Launched carries its terms as ONE struct member that is part of the topic hash - mirror the LaunchTerms tuple 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 / Sold each carry the post-trade reserves, so the price after every trade is in the log itself.
  • Graduated.pool is the hook address, not a pool. The pool handle is the PoolId; PoolRegistered on 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) or amount (Permit2) exactly; never MaxUint256.
  • 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; ethUsed in the quote tells you in advance.
  • 20% for 2 seconds after graduation, both sides, on the pool, while the switch is on. Read quoteFees or just wait.
  • The token list has poolKey but no poolId (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/candles or your own swap indexing.

Suggested test plan

  • GET /launchpad/config; assert curveContracts.chainId == 5042 and activeCurveRelease == "9.0".
  • Pick a curve-trading coin; getCoin it on its providerMeta.curveAddress; quoteBuyFor for your wallet with 1 USDC (1e18); buy; confirm Bought in the receipt; quoteSell the received amount; approve exact; sell.
  • Pick a graduated coin from tokenlist-graduated.json; hash its poolKey and match graduatedPoolId; quote 1 USDC through V4Quoter; execute the buy; read quoteFees; approve through Permit2; sell back.
  • Watch one coin to graduation: confirm the bot flips venue on CurveComplete / Completed without a restart, and does not sell inside the 2-second surcharge.
  • Confirm the bot refuses a buy on an abandoned coin before signing anything.