Hooking · contracts and events

Read the Kitchen from the chain.

There is no Kitchen API yet. Everything the app shows is read straight from the Kitchen's contracts on Robinhood Chain, and anyone can read them the same way, with no key and no agreement.

Robinhood Chain, chain id 4663. Signatures as in the contracts' interfaces. How the Kitchen works is in the docs.

The contracts

chain 4663

Nothing is deployed on Robinhood Chain yet. The addresses below are the ones this build of the app was configured with; a build with none says set at deploy.

ContractWhat it doesAddress
KitchenFactoryThe one-transaction launch: clones the coin, opens its pool, locks the supply, makes the optional first buy. No owner; its only privileged call is the one-shot genesis of $HOOKING.set at deploy
KitchenHookThe Uniswap v4 hook of every Kitchen pool: 0% LP fee, cost basis, the win tip, the anti-snipe window and the price oracle. No owner, no setters after wiring.set at deploy
LiquidityLockerOwns every Kitchen pool's liquidity forever. No function removes liquidity or collects fees.set at deploy
FeeRouterReceives win tips and launch fees and runs the fixed splits: the burns, the creator's $HOOKING, the liquidity band and the team. No owner.set at deploy
KitchenRouterThe app's router: ETH in or out of any coin straight through the PoolManager, and the way to the menu. Holds nothing between transactions, no owner.set at deploy
IngredientRegistryThe menu items the Kitchen accepts: proposed by a multisig, in effect 72 hours later, paused at once by the owner or a guardian key.set at deploy
FlambeDouble or nothing on a buy, with commit and reveal randomness from the house.set at deploy
FlambeVaultFlambé's ETH bankroll: an ERC-4626 vault over WETH that holds every risk cap.set at deploy
ParachuteThe automatic exit. Holds no coins between transactions and has no vault; sells a position once its line is crossed, never below its floor.set at deploy
Every coinA fixed-supply ERC-20 clone that carries each holder's cost basis. One per launch: list them with coinCount() and coinAt(i) on the factory.one per coin
$HOOKINGCoin number one, made by genesis.factory.hooking(), after genesis
Team vestingThe team's 10% of $HOOKING, vesting for 3 + 12 months.in GenesisLaunched, after genesis

Outside the Kitchen

ContractAddress
Uniswap v4 PoolManager0x8366a39CC670B4001A1121B8F6A443A643e40951
Uniswap v4 Quoter0x8Dc178eFB8111BB0973Dd9d722ebeFF267c98F94
Multicall30xcA11bde05977b3631167028862bE2a173976CA11

Events to index

from the interfaces

Names and arguments as in the contracts. The one-shot wiring at deploy is left out.

KitchenFactory

  • Launched(address indexed coin, address indexed creator, address quote, uint256 openPrice, bytes32 poolId)
  • FirstBuy(address indexed coin, address indexed creator, uint256 coins, uint256 paid, uint256 refunded)
  • GenesisLaunched(address indexed hooking, address indexed teamVesting, uint256 teamAllocation)

KitchenHook

  • PoolRegistered(bytes32 indexed id, address indexed coin, address indexed quote)
  • Traded(address indexed coin, address indexed trader, bool isBuy, uint256 amountCoin, uint256 amountQuote, uint256 price)
  • TipCharged(address indexed coin, address indexed seller, uint256 profitQuote, uint256 tipQuote)
  • TipsFlushed(address indexed coin, address indexed quote, uint256 amount)

Every coin

  • BasisUpdated(address indexed account, uint256 cost, uint256 basis)
  • Transfer(address indexed from, address indexed to, uint256 value)

LiquidityLocker

  • LaunchLocked(address indexed coin, bytes32 indexed id, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 coins)
  • BandAdded(address indexed coin, bytes32 indexed id, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 quoteAmount)

FeeRouter

  • TipsCredited(address indexed coin, address indexed quote, uint256 amount)
  • LaunchFeeCredited(address indexed coin, uint256 amount)
  • Burned(address indexed token, uint256 amount, bytes32 indexed source)
  • CreatorAccrued(address indexed coin, address indexed creator, uint256 hookingAmount)
  • CreatorClaimed(address indexed creator, uint256 hookingAmount)
  • LiquidityAdded(address indexed coin, uint256 quoteAmount)
  • TeamPaid(address indexed quote, uint256 amount)
  • Flushed(address indexed coin, address indexed caller, uint256 processed, uint256 reward, uint256 carried)
  • BurnCredited(bytes32 indexed source, address indexed from, uint256 amount)

KitchenRouter

  • Trade(address indexed trader, address indexed coin, bool isBuy, uint256 coinAmount, uint256 ethAmount, address recipient)
  • BoundedBuy(address indexed caller, address indexed coin, address indexed recipient, uint256 ethIn, uint256 coinsOut, uint256 ethBack)

IngredientRegistry

  • Proposed(address indexed ingredient, bytes32 indexed kind, uint64 eta)
  • Cancelled(address indexed ingredient)
  • Activated(address indexed ingredient, bytes32 indexed kind)
  • PausedSet(address indexed ingredient, bool paused, address by)

Flambe

  • ChainCommitted(uint256 indexed chainId, bytes32 anchor, uint256 length, uint256 firstFlip)
  • FlambeRequested(uint256 indexed id, address indexed trader, address indexed coin, uint256 stake)
  • FlipSeeded(uint256 indexed id, bytes32 userSeed, uint256 chainId, uint256 position)
  • SeedRevealed(uint256 indexed id, bytes32 seed)
  • FlambeResolved(uint256 indexed id, bool won, uint256 coinOut)
  • WinPaidInEth(uint256 indexed id, address indexed trader, uint256 eth)
  • FlambeRefunded(uint256 indexed id, address indexed trader, uint256 stake)
  • FlipAbandoned(uint256 indexed id)
  • Owed(address indexed to, uint256 amount)

FlambeVault

  • Reserved(address indexed game, address indexed coin, uint256 amount)
  • Released(address indexed game, uint256 amount, int256 pnl)
  • RedeemRequested(address indexed owner, uint256 shares, uint64 maturesAt, uint64 lapsesAt)
  • RedeemCancelled(address indexed owner, uint256 shares)
  • ProfitSettled(uint256 profit, uint256 toBurn, uint256 toTeam)

Parachute

  • Opened(uint256 indexed id, address indexed owner, address indexed coin, uint256 amount, int24 lineTick, int24 floorTick, uint64 expiresAt)
  • Ejected(uint256 indexed id, address indexed caller, uint256 coinsSold, uint256 ethOut, uint256 toOwner, uint256 reward, uint256 burned)
  • Closed(uint256 indexed id)

Reading them right

  • On a sell through the KitchenRouter, the hook's Traded and TipCharged name the router, which pulls the coins first. The router's Trade in the same transaction names the trader.
  • BasisUpdated gives the holder's total cost and basis, the cost in quote units per 1018 coins. The quote is the zero address for ETH, otherwise $HOOKING.
  • Burned carries its source as a short string in bytes32: tip.hooking, tip.coin, launch, flambe or parachute.
  • A flip is FlambeRequested then FlambeResolved. FlipSeeded carries what a verifier needs besides the reveal, and WinPaidInEth the part of a win its bounded buy could not place.
  • A parachute is Opened, then Ejected or Closed. Its line and floor are ETH-price ticks: log base 1.0001 of the ETH one coin is worth.
  • The vault is also an ERC-4626 and ERC-20 token, with their standard events.
  • The contracts declare a few more events than their interfaces: the hook's TipHeld, Ticket and Owed, and the locker's DustBurned.

Useful reads

view calls

The questions people ask most, and the call that answers each one.

QuestionCall
Every coinfactory.coinCount(), factory.coinAt(i)
Is it a Kitchen coin, and whosefactory.isKitchenCoin(coin), factory.creatorOf(coin)
What a launch costsfactory.launchFee(quoteIsEth)
A coin's pool, quote and agehook.homePool(coin), hook.quoteOf(coin), hook.launchedAt(coin)
A pricehook.meanTick(poolId, secondsAgo): the mean tick over a window, and whether the pool has that much history. The app asks for 0 seconds to get the current tick. hook.quoteValue(coin, amount, window) values coins at the mean over a window.
A holder's cost basiscoin.costOf(holder), the total, and coin.basisOf(holder), in quote units per 1018 coins
Anti-snipe used so farhook.snipeBought(coin, origin)
Tips waiting for a flushhook.claimsHeld(coin)
A creator's $HOOKINGfeeRouter.creatorClaimable(creator); the creator takes it with claimCreator()
Flambé's limits nowflambeVault.maxStake(), flambeVault.hourTaken(coin), flambe.seedsLeft()
A flipflambe.flipOf(id), flambe.seedSlot(id), and flambe.outcome(seed, userSeed, id) to check a result yourself
A parachuteparachute.positionOf(id), and parachute.canEject(id), which answers yes or no with a reason: Ready, NotOpen, Expired, NoPrice, AboveLine, NothingToSell or BelowFloor
A menu item's stateregistry.isActive(item) (activated, paused or not), registry.isLive(item) (activated and not paused), registry.current(kind)

How the app reads the chain

today

The app has no indexer and no database of its own yet. Its screens read the chain over RPC, with viem and react-query, through one data layer that no screen goes around.

  • The present is read with view calls: the coin list from the factory, each coin's name, symbol, metadata, quote and creator, its pool from the hook; prices from the hook's oracle, turned into an ETH price the way the contracts do it, with the $HOOKING pool folded in for a $HOOKING-paired coin; a wallet's balances, cost and approvals; a creator's earnings; quotes, by running the router's own buy and sell as calls or by the Uniswap v4 Quoter; flips and parachutes.
  • The history is read from events with eth_getLogs, from the block this build names in NEXT_PUBLIC_KITCHEN_FROM_BLOCK, over the factory, the hook, the router, the FeeRouter, Flambé, Parachute and the locker, in pieces of 5,000 blocks. After the first read only new blocks are read, and if the chain changed under the last block read, it is read again from the start. A build with no start block shows the present and no history.
  • In the browser the calls go to a route on the same site, /api/rpc, which forwards a small read-only set of JSON-RPC methods to the chain's node, unless a build points NEXT_PUBLIC_RPC at a node of its own. Transactions are sent by your wallet, never by that route.

The same read, from your own code

Every launch since a block, with viem (any Node, Bun or Deno that runs it):

import { createPublicClient, http, parseAbiItem } from "viem";

// The chain's public node turns away requests that do not look like a browser's.
const client = createPublicClient({
  transport: http("https://rpc.mainnet.chain.robinhood.com", {
    fetchOptions: {
      headers: {
        "user-agent":
          "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
      },
    },
  }),
});
const FACTORY = "0x..."; // the KitchenFactory
const START = 0n; // the block before the Kitchen was deployed

const launched = parseAbiItem(
  "event Launched(address indexed coin, address indexed creator, address quote, uint256 openPrice, bytes32 poolId)",
);
const logs = await client.getLogs({ address: FACTORY, event: launched, fromBlock: START, toBlock: START + 4999n });
for (const log of logs) console.log(log.args.coin, log.args.creator);

Ask for a few thousand blocks at a time: public nodes cap the range of one eth_getLogs, which is why the app reads 5,000 blocks a call.

The indexer

milestone 5

The indexer is the next piece. When it exists it replaces the history read above: it fills the same index from its own tables, and no screen changes. Until then there is no Kitchen REST API and no key to ask for; read the contracts directly, as the app does.

If this page and the chain ever disagree, the chain is right. updated 16 October 2026