Skip to content

Hood market integration

This page describes the minimum on-chain information required to integrate Candle markets on Robinhood Chain.

PropertyValue
Chain ID4663
Native assetETH
RPChttps://rpc.mainnet.chain.robinhood.com
Explorerhttps://robinhoodchain.blockscout.com

There are three canonical contract generations, and all three are live. Candle first deployed its launch stack on 2026-08-03, redeployed it at block 30442973 (2026-08-07) to add on-chain token metadata, and redeployed it again at block 63312133 (2026-09-15, the launch-stack-v2 generation: economics pinned into the factory, the token deployer split out, escaped tokenURI). A curve keeps trading and migrating through the contracts of the generation that created it, indefinitely, so an integrator must index all three generations; treating an earlier generation as deprecated will break live markets. Branch on block height, not on a date.

Each generation’s identity root is its CandleCurveRegistry, permanently bound to its CandleCurveFactory:

GenerationCreated at blockRegistryFactory
Third (current)≥ 633121330xb789E2711445488407c120563B29dF7c376cC9Ea0xD08f8489F026957EdeD3Bb8Ef8A9d151A7B1DF22
Second30442973 to 633121320x75934c16162075583435358f9F042D8D6E42Bd5C0x63a289eB0F620fE7701D314022F52783547D8F3a
First< 304429730xFD54D094ad93349CA316bA309A3C8573E3D6C0cd0xdaCfdBbb62FFEB32917547e130464CDc9747BdC2

On the second and third generations, curve contracts are CREATE2-deployed by a separate CandleCurveDeployer (0x8313F0677ec1f26452D91B655a4A9056CE5dA1A6 on the third, 0x15257Bf766509388e72b523F1A0bF2C1697eE4F1 on the second), not by the factory itself. To derive a curve address ahead of time, read the deployer from factory.deployer() rather than hardcoding it; the factory no longer exposes predictCurveAddress.

Index successful CurveRegistered logs emitted by all three canonical registries. Each log identifies:

  • The curve contract.
  • The launched base-token contract.
  • The quote token (address(0) means native ETH).
  • The approved migrator.
  • The per-market fee recipient.
  • The curve configuration hash and implementation version.
  • The CNDL-staker allocation.

The factory emits CurveCreated in the same transaction with the creator, DEX version, configuration hash, and launcher salt. Treat the registry log as the admission proof and the factory log as additional launch metadata.

For a candidate curve:

  1. Call isRegistered(curve) on each canonical registry and require true on one of them.
  2. Call getRecord(curve) on that registry and require active == true.
  3. Require curveForBaseToken(record.baseToken) == curve.
  4. Read execution and lifecycle state from that curve address.

For a candidate token, call curveForBaseToken(token) on each registry. A zero address on all three means it is not a canonically registered Candle launch. For a nonzero result, perform the curve checks above and require getRecord(curve).baseToken == token.

Contract roleIdentification rule
CurveActive record on any of the three canonical registries
Launched tokenReverse mapping from curveForBaseToken to an active curve record
v3 curveRecord migrator is 0xa528D44671aE25c6245D970c26306D4e2C36196D (third), 0x1F495F6326908f8e595b18BF6754F2a066Fd3846 (second), or 0x5A51Fc39cFA93B14bD184D76F7Dc2C00aC13620b (first)
v4 curveRecord migrator is 0x43BF6B5F0Da1a53054b4a580B6cEC10DD225F52C (third), 0xeB4aAF61c5BC8c5cc6136dd8D9fdd89146B8D59a (second), or 0x934349F158b9e2BCA0d8324626962C01a1De6Bd0 (first)
Fee recipient/splitterAddress recorded for that curve; do not assume one global recipient
Migrated poolConfirmed curve lifecycle plus the canonical migrator’s migration event

The migrator is also readable directly from any curve as migrator(); it is immutable per curve. Never assume one global migrator.

Do not identify Candle contracts by contract name, matching function selectors, bytecode similarity, token symbol, deployer history, or an API label. Those are useful discovery hints but can be copied by another deployment. The canonical registry record is the provenance check.

Native-ETH curves use:

buy(uint256 minAmountOut) payable
sell(uint256 baseIn, uint256 minAmountOut)

ERC-20-quoted curves require approval of the quote token followed by:

buyWithQuote(uint256 quoteIn, uint256 minAmountOut)

Selling requires approval of the launched base token to the curve.

Before building calldata, read the curve’s quote token and lifecycle. Calling the native buy on an ERC-20 curve, or the ERC-20 buy on a native curve, reverts with WrongQuoteMode.

A buy that would cross the threshold is capped. Use the capped quote when calculating minAmountOut; the remainder is returned as refund in the Bought event and transaction accounting.

Once lifecycle is Graduated, both buys and sells are closed. Do not route to v3 or v4 until migration is confirmed.

  • Fee: 3000
  • Tick spacing: 60
  • Factory: 0x1f7d7550B1b028f7571E69A784071F0205FD2EfA
  • WETH: 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73

The v3 pool is normally pre-created when the curve is launched. Pool existence is therefore not proof that migration has occurred. Route only after the curve reaches Migrated and the migrator’s activation transaction is confirmed.

  • PoolManager: 0x8366a39CC670B4001A1121B8F6A443A643e40951
  • Fee: 3000
  • Tick spacing: 60
  • Hook: 0x1517fdbf49616D3c31b2b549Ea7EA90FDabb6000 (third generation), 0x299FbBECBdBec82B56117d7593a89fe64F77a000 (second), or 0x000509f35530F91068684Fef08AF0405486eE000 (first)

The v4 PoolKey must include the correctly ordered currencies, fee, tick spacing, and hook. Native ETH is represented by the zero-address currency in the PoolKey, and it always sorts first. Use the hook that matches the curve’s generation (which registry it is registered on); a PoolKey built with another generation’s hook derives a different PoolId and finds nothing. The pool does not exist before migration.

Index at minimum:

  • Factory CurveCreated
  • Registry CurveRegistered
  • Curve Bought, Sold, Graduated, LifecycleChanged, and MigratedToDex
  • Curve recovery events
  • v3/v4 migrator Migrated and fee-collection events
  • Fee splitter distribution, deferred payout, and claim events

Tokens launched by the second and third generations (block ≥ 30442973) carry their metadata on-chain, and the token contract is authoritative for it:

  • Getters: description(), image(), socials() (a JSON string), metadataVersion() (0 means never edited), and creator().
  • tokenURI() returns base64 JSON for ERC-721-convention tooling but omits socials; prefer the individual getters.
  • Only the creator can revise metadata, via setMetadata. Every revision emits MetadataUpdated(address indexed editor, uint64 indexed version, string description, string image, string socials), and version 0 is emitted from the constructor, so an indexer can rebuild current metadata from logs alone without any eth_call.

First-generation tokens have none of these fields; the calls revert, permanently. They cannot be retrofitted, so a reverting metadata getter on an older token is expected state, not an error.

On-chain registry and contract state are authoritative for market identity and execution. Candle and HMC provide lower-latency discovery, images, social links, candles, trades, holders, and wallet enrichment. Treat those services as indexing and metadata layers rather than replacements for canonical contract checks.

Every third-generation contract on this page is source-verified on Blockscout, as is every second-generation one, so their full ABIs are available from the explorer (the Contract tab, or GET https://robinhoodchain.blockscout.com/api/v2/smart-contracts/{address}). Two gaps matter to an indexer:

  • Per-launch curves and tokens are verified one instance at a time. Blockscout does not extend a verified curve or token to later launches, so any given launch may show as unverified. Every curve in a generation exposes the same ABI, as does every token, so read it from a verified instance: the third generation’s first launch is curve 0x1eA6E3a05479E5bA0B3D69EFDfce201D25325F66 and token 0x6d630d02309d1bD1cA90EFD73Be2659E404c2fBD.
  • Three first-generation contracts are unverified: the factory, the V3 migrator, and the hook. The first-generation registry and V4 migrator are verified.

For convenience, the exact surface this page documents, as human-readable fragments accepted directly by viem’s parseAbi and ethers’ Interface:

// CandleCurveRegistry (all three generations share this bytecode)
const registryAbi = parseAbi([
"struct CurveRecord { address baseToken; address quoteToken; address migrator; address feeRecipient; bytes32 configHash; bytes32 implementationVersion; uint16 stakerAllocationBps; bool active; }",
"function isRegistered(address curve) view returns (bool)",
"function getRecord(address curve) view returns (CurveRecord memory)",
"function curveForBaseToken(address baseToken) view returns (address)",
"event CurveRegistered(address indexed curve, address indexed baseToken, address indexed quoteToken, address migrator, address feeRecipient, bytes32 configHash, bytes32 implementationVersion, uint16 stakerAllocationBps)",
])
// CandleCurveFactory (current generation)
const factoryAbi = parseAbi([
"function deployer() view returns (address)",
"event CurveCreated(address indexed curve, address indexed baseToken, address indexed creator, uint8 dexVersion, bytes32 configHash, bytes32 launcherSalt)",
])
// CandleCurve (per launch)
const curveAbi = parseAbi([
"function baseToken() view returns (address)",
"function quoteToken() view returns (address)",
"function lifecycle() view returns (uint8)",
"function migrator() view returns (address)",
"function migrationThreshold() view returns (uint256)",
"function stakerAllocationBps() view returns (uint16)",
"function buy(uint256 minAmountOut) payable returns (uint256 baseOut)",
"function buyWithQuote(uint256 quoteIn, uint256 minAmountOut) returns (uint256 baseOut)",
"function sell(uint256 baseIn, uint256 minAmountOut) returns (uint256 quoteOut)",
"event Bought(address indexed buyer, uint256 quoteIn, uint256 baseOut, uint256 refund)",
"event Sold(address indexed seller, uint256 baseIn, uint256 quoteOut)",
"event Graduated(uint256 quoteReserve)",
"event MigratedToDex(uint256 baseToMigrator, uint256 quoteToMigrator)",
"event LifecycleChanged(uint8 indexed previous, uint8 indexed next)",
])
// CandleToken (second and third generations; these revert on first-generation tokens)
const tokenAbi = parseAbi([
"function decimals() view returns (uint8)",
"function creator() view returns (address)",
"function description() view returns (string)",
"function image() view returns (string)",
"function socials() view returns (string)",
"function metadataVersion() view returns (uint64)",
"function tokenURI() view returns (string)",
"event MetadataUpdated(address indexed editor, uint64 indexed version, string description, string image, string socials)",
])