# Caffee — token & bonding-curve integration reference **For data providers, trading terminals, aggregators, and bots** (Codex/Defined, DexScreener, GeckoTerminal, GMGN, Axiom, custom indexers). Everything here is **read-only, on-chain, and permissionless** — you do not need anything from us to integrate. This page is the package to build from. - **Product:** Caffee (caffee.fun) — a pump.fun-style token launchpad + bonding-curve DEX. - **Chain:** Robinhood Chain — **EVM, chain id `4663` (`0x1237`)**, native coin **ETH** (18 dec). - **RPC:** `https://rpc.mainnet.chain.robinhood.com` - **Explorer:** `https://robinhoodchain.blockscout.com` (Blockscout; Etherscan does not index 4663) - All amounts are `uint256` base units (wei / 1e18). Format only at display time. A Caffee token has **two lifecycle states**, and you index them differently: | State | Where it trades | How you index it | |---|---|---| | **On curve** (pre-graduation) | The token's own **CaffeeCurve** contract (constant-product with virtual reserves) | This doc — enumerate curves, read state, index `Buy`/`Sell` | | **Graduated** | A **canonical Uniswap-V2 pair** (LP burned to `0x…dead`) | Your existing Uniswap-V2 indexer — nothing Caffee-specific | Graduation is a one-way migration announced by the `Graduated` event (below). After it, the token is just a standard Uniswap-V2 pool on Robinhood Chain — index it exactly like any other. --- ## 1. Addresses ``` CaffeeLaunch (factory, V2) 0xdeDc13eAA14462644dD99087eB408515D7D2aD56 TokenMetadata (registry) 0xe82bd8EEBe34df851a6Bc33629BE6Ed23601c81D Uniswap-V2 Factory (DEX) 0x8bcEaA40B9AcdfAedF85AdF4FF01F5Ad6517937f (graduation target; canonical) WETH 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73 (all graduated pairs are WETH-quoted) ``` > The factory address can change across major versions (there was a V1 → V2 migration). Always > discover the current factory from this doc or from the `Launched` event stream, and treat a curve > as authoritative for its own token via `curveOf`. Each launched token has exactly **one** curve. Total supply is fixed: **1,000,000,000 × 1e18** (`CURVE_TOTAL_SUPPLY = 1e27`). Trading fee is **1% (100 bps)**, already reflected in the quote functions below. --- ## 2. Enumerate every token (no indexer required) The factory keeps an append-only array of curves (curves are never removed): ``` curvesLength() → uint256 selector 0xe5498a57 curves(uint256 index) → address curve selector 0x1bf7d749 ``` For each curve, get its ERC-20 and creator: ``` token() → address token selector 0xfc0c546a creator() → address creator selector 0x02d05d3f ``` Reverse lookup (token → curve; returns `0x0` if the token isn't a Caffee curve token): ``` curveOf(address token) → address curve selector 0x05adc47e (on the factory) ``` **Backfill / real-time alternative:** replay the `Launched` event (§5) from the factory — every token ever created is one `Launched` log, giving `(token, curve, creator, name, symbol)` in one pass. --- ## 3. Read a curve's live state All on the **curve** contract. Return types are what our production frontend decodes: ``` spotPrice() → uint256 wei per token × 1e18 selector 0x398482d8 == virtualEthReserves * 1e18 / virtualTokenReserves virtualEthReserves() → uint256 effective ETH reserve selector 0xb2a39d09 virtualTokenReserves() → uint256 effective token reserve selector 0x1655bc62 realEthReserves() → uint256 ETH actually in curve selector 0x948ce1d3 (= "raised") realTokenReserves() → uint256 tokens left on curve selector 0x5c25c6dd curveSupply() → uint256 tokens allocated to curve selector 0x2138a4c0 tokensSold() → uint256 == curveSupply - realTokenReserves selector 0x518ab2a8 graduated() → bool migrated to DEX? selector 0xe7c2b772 pair() → address Uniswap-V2 pair (0x0 until graduated) selector 0xa8aa1b31 token() → address the ERC-20 selector 0xfc0c546a creator() → address launcher selector 0x02d05d3f ``` ### Derived metrics (exact formulas our UI uses) ``` priceWei = virtualEthReserves * 1e18 / virtualTokenReserves # = spotPrice() marketCapWei = spotPrice() * CURVE_TOTAL_SUPPLY / 1e18 # = spotPrice() * 1e9 raisedWei = realEthReserves() progressPct = tokensSold() / curveSupply() * 100 # bonding-curve fill % graduated = graduated() # authoritative flag ``` **Graduation ETA** (informational only — the `Graduated` event is authoritative): ``` ethToGraduateWei ≈ virtualEthReserves * realTokenReserves / (virtualTokenReserves - realTokenReserves) ``` ### Quotes (constant-product, fee included) ``` getBuyQuote(uint256 ethInWei) → uint256 tokensOut selector 0xb390452c getSellQuote(uint256 tokenIn) → uint256 ethOutWei selector 0x0812530e ``` --- ## 4. Execute trades on the curve (for terminals that route orders) Pre-graduation, buy/sell happen **directly on the curve** (no router). Post-graduation, route through the Uniswap-V2 router like any WETH pair. ``` buy(uint256 minTokensOut) payable selector 0xd96a094a # msg.value = ETH in; minTokensOut = slippage guard sell(uint256 amount, uint256 minEthOut) selector 0xd79875eb # requires prior ERC-20 approve(curve, amount) approve(address curve, uint256 amount) selector 0x095ea7b3 # standard ERC-20, on the token ``` Always pass a non-zero `minOut` computed from `getBuyQuote`/`getSellQuote` with your slippage tolerance. Our app uses 5%. --- ## 5. Events to index Topics below are the deployed, on-chain values (verify against your own logs). `indexed` args are topics; the rest are ABI-decoded from `data`. ### On each **curve** ```solidity // topic0 = 0x00f93dbdb72854b6b6fb35433086556f2635fc83c37080c667496fecfa650fb4 event Buy(address indexed buyer, address indexed to, uint256 ethIn, uint256 tokensOut, uint256 refund); // topic0 = 0xed7a144fad14804d5c249145e3e0e2b63a9eb455b76aee5bc92d711e9bba3e4a event Sell(address indexed seller, uint256 tokensIn, uint256 ethOut); // topic0 = 0x1c858049e704460ab9455025be4078f9e746e3fd426a56040d06389edb8197db event Graduated(address indexed pair, uint256 ethToLp, uint256 tokensToLp); ``` - **`Buy.ethIn`** is the ETH the curve received **net of fee/refund** — i.e. the actual reserve delta. Do **not** additionally subtract `refund` (it's already excluded). `refund` is the overshoot returned to the buyer when a buy would exceed the remaining curve supply. - Trade price of a fill: `Buy` → `ethIn / tokensOut`; `Sell` → `ethOut / tokensIn` (both ×1e-18-scaled). - **`Graduated`** fires once, at migration. `pair` is the new Uniswap-V2 pool — hand off to your DEX indexer from that block on. LP is burned to `0x…dead` (liquidity is locked, not rug-able). ### On the **factory** (`0xdeDc…aD56`) ```solidity // topic0 = 0xc5a807b0033def274292e9d3ba676e6fcfb69d9d383ccf9b69112237bd95def9 event Launched(address indexed token, address indexed curve, address indexed creator, string name, string symbol); ``` One per new token — your create/discovery feed. ### OHLCV / candles Build candles client-side from the `Buy`/`Sell` stream: per trade, `price = ethIn/tokensOut` (buy) or `ethOut/tokensIn` (sell); bucket by time; volume = Σ ETH legs. (This is exactly how the caffee.fun chart is built — there is no separate price oracle pre-graduation.) --- ## 6. Token metadata (image / description / socials) Off-chain-style metadata is stored on-chain in the **TokenMetadata** registry (`0xe82bd8…c81D`), keyed by token address: ``` metadata(address token) → (image, description, ...socials) selector 0x2ba21572 getMany(address[] tokens) → batch selector 0xf1e751fc // event, topic0 = 0xedcaa71483243d7a5ca5e6114a75dd37a9a11c7d8c8ba9360a403d71300365e4 event MetadataSet(address indexed token, ...) ``` Name/symbol/decimals/totalSupply come from the ERC-20 itself (standard selectors). Registry is bound to the current factory version; a token launched under an older factory may have metadata in an older registry. --- ## 7. Field mapping → common aggregator schemas For Codex/Defined-style launchpad ingestion (their fields ← our reads): | Aggregator field | Caffee source | |---|---| | `price` | `spotPrice()` (÷1e18) | | `marketCap` | `spotPrice() * 1e9` (wei) | | `graduationPercent` | `tokensSold() / curveSupply() * 100` | | `completed` / `migrated` | `graduated()` | | `poolAddress` / `migratedPoolAddress` | `pair()` (0x0 until graduated) | | `migratedAt` | block of the `Graduated` event | | `creation timestamp` | block of the `Launched` event | | dev / creator wallet | `creator()` (also indexed in `Launched`) | | `name` / `symbol` / `address` | ERC-20 standard reads / `Launched` args | | trade stream | `Buy` / `Sell` logs | For DexScreener/GeckoTerminal: **graduated** tokens need no custom work (canonical Uniswap-V2 pool). **Pre-graduation** curves need launchpad-level integration — this doc is that spec. --- ## 8. Hosted read API (optional — we run it for you) Everything above reads straight from the chain. If you'd rather consume a feed than run your own indexer, we host a **read-only HTTP + SSE API** at **`https://caffee.fun/api`** (CORS-open, no key). It mirrors the exact math in this doc, so it can't disagree with caffee.fun. Native endpoints: ``` GET /api/tokens?sort=mcap|new&graduated=0|1&limit= list (price/mcap in ETH+USD, progress, graduated, pair) GET /api/token/:address one token, full curve state GET /api/token/:address/trades?limit=&fromTs= Buy/Sell trade stream GET /api/token/:address/ohlcv?res=1m|5m|15m|1h|4h|1d candles (built from Buy/Sell) GET /api/stats launchpad aggregate GET /api/stream Server-Sent Events: launched | trade | graduated ``` CoinGecko / GeckoTerminal **on-chain DEX standard** (for their launchpad integration): ``` GET /api/cg/latest-block GET /api/cg/asset?id= GET /api/cg/pair?id= GET /api/cg/events?fromBlock=&toBlock= ``` The API is a convenience layer — the on-chain reads in §2–§6 remain the source of truth, and graduated tokens are handed off to the canonical Uniswap-V2 pool (index those with your normal DEX indexer). --- ## 9. Trust / caveats (read before listing) - Contracts are **unaudited** (internal review only). Do not represent Caffee tokens as vetted. - **Graduation griefability (inherited, present today):** anyone can pre-seed the token/WETH Uniswap pair with dust so the pristine-pair check defers migration; the curve stays live (holders can always sell back), but the DEX migration can be blocked. Treat `graduated()` / the `Graduated` event as the only migration source of truth. - Contracts are **source-verified on Blockscout** (factory, curve, token, and registry — full match). - Selectors/topics here are copied from the production frontend (`lib/constants.ts`) and the deployed `CaffeeTradingV2.sol`. Re-verify against your own node before mainnet routing. Questions / partnership / to get Caffee added as a launchpad on your platform: reach out on X at [@caffeefun](https://x.com/caffeefun) — the only official Caffee account.