RIFF documentation

Part I explains the protocol: how a launch works, how trading and fees work, and what protects a fresh token in its first blocks. Part II is a contract-first integration surface for anyone building against RIFF directly: network details, contract addresses, onchain events, and read examples in viem.

1. Overview

RIFF is a permissionless memecoin launchpad on Robinhood Chain. Anyone can launch a token in a single transaction: the token is deployed, its liquidity position is opened and locked, and trading can begin immediately in the same pool for the life of the token.

RIFF has no bonding curve and no migration step. There is no protocol buyback or burn mechanism, and no separate governance token. The one governance feature RIFF does ship is a creator-protected community takeover (CTO) process for the fee payout wallet, described in section 7.

2. Anatomy of a launch

A launch is a single atomic transaction. In one call the factory deploys the token, opens a single-sided, locked Uniswap V3 position for it, charges the launch fee, and (optionally) executes the creator's dev-buy from any leftover transaction value, all in one block.

  • Fixed supply: 1,000,000,000 tokens, minted once at launch.
  • Pool: 1% fee tier, paired against WETH.
  • Liquidity is locked from launch: there is no bonding curve and no migration event.
  • Launch fee: 0.0005 ETH, paid to the protocol.

3. Launch protection

Every launch opens with a short anti-snipe window, measured in blocks rather than time, so it applies evenly regardless of network conditions.

  • The window lasts 2 blocks from launch.
  • On the launch block itself, only the creator's atomic dev-buy can buy: no other buyer can get in before the creator.
  • For the rest of the window, each wallet can hold at most 5% of supply and buy at most 5.5% of supply in total.
  • The creator's dev-buy is itself capped at 5% of supply.
  • Sells and wallet-to-wallet transfers are never restricted, at any point.
  • All limits end automatically once the window closes; trading is unrestricted after that.

4. Trading and pricing

Trading is market-only: every trade goes through the token's Uniswap V3 pool at the 1% fee tier. There is no separate launchpad order book and no off-chain matching. The price you see is the pool's live price, read directly from its state.

TermMeaning
PriceThe current price of one token in ETH, read from the pool's live state (slot0).
Market capPrice multiplied by the fixed total supply.
FDVFully diluted value. Since supply is fixed, FDV equals market cap unless tokens have been burned.
Price impactHow much a trade moves the pool price; larger trades move it more.
SlippageThe maximum price movement a trader will accept before a trade reverts.
LiquidityThe ETH and token value available in the pool for trading.

5. Graduation

A token graduates when the paired WETH principal in its pool reaches 4.2 ETH. Graduation is a one-way milestone: once reached, it stays reached. It does not change how the token trades. There is no migration; trading continues in the same pool before and after graduation. Graduation is a size milestone, not a quality signal.

6. Fees

Every trade pays a 1% fee. The split between the creator and the protocol is snapshotted per token at launch and never changes for that token afterward.

  • Launch config: 80% to the creator, 20% to the protocol.
  • The protocol's share is capped at 50% for any token.
  • Creators can claim accrued fees from the RIFF interface at any time.
  • Unclaimed fees may be auto-claimed and routed to the creator's payout wallet.
Note: the split above is the live launch configuration on the deployed contracts. It is snapshotted per token at launch and never changes for that token, so always read the token's actual share on-chain (see section 15) before integrating.

7. Governed community takeover (CTO)

If a creator disappears, the fee payout wallet for their token can be reassigned through a governed, on-chain process rather than an off-chain form. This is a differentiator versus other launchpads.

  • The protocol owner proposes a new payout wallet.
  • A 14-day on-chain timelock begins, during which the current creator can veto at any time.
  • After the timelock, the proposal can be executed, moving the payout wallet.
  • A CTO can never route the creator's fee share to the protocol, and it never changes the fee split itself: only the payout wallet moves.
  • The creator can veto by explicitly cancelling the proposal, or simply by acting (any call that sets their own fee redirect cancels a pending proposal automatically).
Why it matters: the takeover path is fully on-chain and time-boxed, the creator holds a standing veto for the entire window, and the fee split can never be altered by a takeover. No off-chain form and no administrative discretion decide who receives a token's fees.

8. Editable metadata and burns

Every RIFF token is self-describing on-chain: its name, symbol, logo, description, and social links are readable directly from the token contract, without depending on any off-chain database.

  • The creator (only) can edit a token's social links after launch.
  • Burns are simply transfers to the zero address. There is no separate protocol burn mechanism. The indexer counts burns per token from these transfers.

9. Risk disclosures

  • Tokens on RIFF are user-created and experimental. Anyone can launch anything.
  • Always check the token address you are interacting with.
  • Prices can move fast and liquidity can be thin, especially for small or new tokens.
  • Values shown in the interface (price, market cap, FDV) are estimates.
  • RIFF is an interface to public, permissionless smart contracts. It is not investment advice.

10. Network

FieldValue
NetworkRobinhood Chain
Chain ID4663
Native assetETH
Public RPChttps://rpc.mainnet.chain.robinhood.com
Explorerrobinhoodchain.blockscout.com
Pool fee10000 (1%)
Launch fee0.0005 ETH
Supply1,000,000,000 (1e9), fixed per token

11. Contracts

The deployed RIFF contracts, plus the shared Uniswap infrastructure on Robinhood Chain:

ContractAddress
WETH0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73
Position manager0x73991a25C818Bf1f1128dEAaB1492D45638DE0D3
Swap router0xCaf681a66D020601342297493863E78C959E5cb2
RIFF factory0x059c45DB0fca09aACbe0de62f396512792ef6BaE
RIFF locker0x2f59694e9220e138344a13B1432056a68F7D165F
Liquidity locked at launch Fixed supply Fee split snapshotted per token Protocol share capped at 50% Governed CTO, 14-day creator veto

12. Onchain events

To index RIFF activity, watch the factory's TokenLaunched event, register each pool it announces, and index that pool's Swap events for trades.

Event signatures (topic0)
TokenLaunched(address,address,address,address,uint256,uint256)
  topic0: 0x8d4aad4953d0ca700d468f3753aa14432d1b35b43ec6409f051fb6aa43a89607

FeesClaimed(address,address,address,address,uint256,uint256,uint256,uint256)
  topic0: 0x1547f2bd1a244399782ebde22047e2ede698ecdc4d6c7d4b3c4e2435f1e47f7a

CtoProposed(address,address,uint64)
  topic0: 0x0c571ebfe82bccfab5a8bf9c83f44a9b169997f206310d489ade0ff794ebcc41

CtoExecuted(address,address)
  topic0: 0x66efaf5c3bbaa56182b3d306b97344fa75d2ac784eae0be617bd07bf8dea55b7
viem: backfilling TokenLaunched
import { createPublicClient, http, parseAbiItem } from "viem";

const rhChain = {
  id: 4663,
  name: "Robinhood Chain",
  nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
  rpcUrls: { default: { http: ["https://rpc.mainnet.chain.robinhood.com"] } },
};
const client = createPublicClient({ chain: rhChain, transport: http() });

// factory address is published at launch.
const launches = await client.getLogs({
  address: factory,
  event: parseAbiItem(
    "event TokenLaunched(address indexed token, address indexed deployer, address pairedToken, address pool, uint256 positionId, uint256 supply)"
  ),
  fromBlock: "earliest",
  toBlock: "latest",
});
Note: the public RPC times out on wide eth_getLogs ranges. Backfill in bounded block chunks starting from the factory's deployment block.

13. Reading token state

Every RIFF token is self-describing on-chain: name, symbol, logo, description, socials, and the restriction window can all be read directly from the token contract.

viem: token getters
import { parseAbi } from "viem";

// The launch token is self-describing on-chain.
const tokenAbi = parseAbi([
  "function name() view returns (string)",
  "function symbol() view returns (string)",
  "function decimals() view returns (uint8)",
  "function totalSupply() view returns (uint256)",
  "function logo() view returns (string)",
  "function description() view returns (string)",
  "function creator() view returns (address)",
  "function liquidityPool() view returns (address)",
  "function socials() view returns (string twitter, string telegram, string website, string discord, string farcaster)",
  "function restrictionEndBlock() view returns (uint256)",
]);

const [name, symbol, pool, creator] = await Promise.all([
  client.readContract({ address: token, abi: tokenAbi, functionName: "name" }),
  client.readContract({ address: token, abi: tokenAbi, functionName: "symbol" }),
  client.readContract({ address: token, abi: tokenAbi, functionName: "liquidityPool" }),
  client.readContract({ address: token, abi: tokenAbi, functionName: "creator" }),
]);
viem: factory launch record
const factoryAbi = parseAbi([
  "function getLaunchedToken(address token) view returns ((bool exists, address token, address deployer, address pairedToken, address positionManager, uint256 positionId) launched)",
]);
const { launched } = await client.readContract({
  address: factory, abi: factoryAbi, functionName: "getLaunchedToken", args: [token],
});
// launched.deployer is the creator payout default; launched.pairedToken is WETH.

14. Pricing and graduation

Price is read directly from the pool's slot0. Token and WETH both use 18 decimals, so no decimal scaling is needed; the only adjustment is ordering token0 versus token1.

viem: price from slot0
import { parseAbiItem } from "viem";

const [sqrtPriceX96] = await client.readContract({
  address: pool,
  abi: [parseAbiItem(
    "function slot0() view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked)"
  )],
  functionName: "slot0",
});

// Token and WETH both use 18 decimals, so no decimal scaling is needed.
const isToken0 = token.toLowerCase() < pairedToken.toLowerCase();
const ratio = Number(sqrtPriceX96) / 2 ** 96;
const token1PerToken0 = ratio * ratio;
const priceInWeth = isToken0 ? token1PerToken0 : 1 / token1PerToken0;

// ethUsd from any ETH oracle.
const priceUsd = priceInWeth * ethUsd;
const marketCapUsd = priceUsd * 1_000_000_000; // fixed supply
const fdvUsd = marketCapUsd; // supply is fixed; FDV equals market cap unless tokens are burned
viem: graduation status
const [pairedPrincipal, threshold, graduated] = await client.readContract({
  address: factory,
  abi: [parseAbiItem(
    "function graduationStatus(address token) view returns (uint256 pairedPrincipal, uint256 threshold, bool graduated)"
  )],
  functionName: "graduationStatus",
  args: [token],
});
const progress = Number(pairedPrincipal) / Number(threshold); // 0..1, the progress line

15. Fees and CTO state

The locker holds the per-token fee split and any pending CTO proposal. Reading it tells you the live, deployed values for a given token, which may differ from the launch config (see section 6).

viem: locker state
import { parseAbi, zeroAddress } from "viem";

const lockerAbi = parseAbi([
  "function tokenProtocolFeeShares(address token) view returns (uint256)",
  "function feeRedirects(address token) view returns (address)",
  "function protocolFeeRecipient() view returns (address)",
  "function pendingCto(address token) view returns (address newWallet, uint64 executeAfter)",
]);

const [protocolShare, redirect, pending] = await Promise.all([
  client.readContract({ address: locker, abi: lockerAbi, functionName: "tokenProtocolFeeShares", args: [token] }),
  client.readContract({ address: locker, abi: lockerAbi, functionName: "feeRedirects", args: [token] }),
  client.readContract({ address: locker, abi: lockerAbi, functionName: "pendingCto", args: [token] }),
]);

const creatorSharePercent = 100 - Number(protocolShare); // launch config: 90
const creatorPayout = redirect === zeroAddress ? deployer : redirect;
// pending.executeAfter is the unix time a proposed CTO can execute (0 = none). The 14-day veto
// window is CTO_TIMELOCK; the creator can cancel any time before it elapses.

16. RIFF Indexer API

For teams that do not want to run their own indexer, RIFF publishes a REST and WebSocket read layer. The base URL will be published at launch.

RouteDescription
GET /tokensList tokens, sortable (mcap, trending, lasttrade, new, oldest).
GET /token/:addressSingle token detail.
GET /token/:address/candlesOHLC candles.
GET /token/:address/tradesRecent trades.
GET /token/:address/holdersHolder list.
GET /token/:address/feesAccrued fee state.
GET /searchToken search.
GET /wallet/:address/launchesTokens launched by a wallet.
GET /wallet/:address/holdingsTokens held by a wallet.
GET /wallet/:address/feesFees earned by a wallet.
GET /statsPlatform-wide daily stats.
WebSocketA live feed of updates, for teams that want push updates instead of polling.

Selected response fields: imageUrl, launchBlock, creatorFeeBps, protocolFeeBps, graduated, burnedTokens, burnedPct on tokens; type, ethAmount, tokenAmount, priceUsd, wallet, isDev, ageSeconds, txHash on trades.

17. Reference and support

  • A reference token address will be published at launch.
  • Contracts are immutable: new versions ship as new addresses, never upgrades in place.
  • Onchain data is public and free to read by anyone, with or without RIFF's indexer.
  • Usage of RIFF and any token launched on it is at your own risk (see section 9).
  • Support contact will be published at launch.