technical reference
ZeroHood — Integration Docs
This page is for indexers, scanners, security tools and anyone else who needs to programmatically recognize, price, and evaluate tokens launched through ZeroHood on Robinhood Chain (chain ID 4663). Everything below is verifiable directly on-chain — no API key, no trust required.
1. Overview
ZeroHood is a fair-launch platform on Robinhood Chain. Anyone can deploy a new fixed-supply ERC-20 in one transaction that immediately becomes a real, tradeable Uniswap v4 pool — no presale, no team allocation, no graduation wait, tradeable and priceable the same block it launches.
Launches and trades are submitted directly by the user's own wallet (they pay their own gas; there is no relayer in the transaction path). The one exception is claiming creator fees, which is sponsored server-side via a relayer-signed EIP-712 authorization so a creator never needs gas to withdraw what they earned.
The token supply is a fixed 1,000,000,000 (18 decimals), and the entire supply is seeded into the pool single-sided (token-only, zero WETH) at launch — see the single-sided liquidity model below. This is what makes launches cost only gas while still giving buyers deep liquidity from block one.
2. Contract addresses
Chain: Robinhood Chain, ID 4663. Everything below is canonical and immutable.
The vault and escrow are also readable straight off the factory (factory.vault() / factory.feeEscrow()), so they stay correct even if the factory is ever redeployed to a new address.
3. Detecting a ZeroHood launch
Watch one event on InstantPoolFactory to discover every launch with full metadata in a single log read — no follow-up eth_call per token:
event Launched(
address indexed token,
uint256 indexed tokenId, // Uniswap v4 LP position NFT id (on the canonical PositionManager)
address indexed creator, // the wallet that launched it (msg.sender)
bytes32 claimKey, // creator fee-claim key (wallet- or social-derived, see Creator fee claims below)
string name,
string symbol,
string description,
string imageURI, // https:// or ipfs:// — required at launch, never empty
string website, // optional, "" if not set
string twitter, // optional display URL, e.g. https://x.com/handle
string telegram, // optional display URL, e.g. https://t.me/group
string xHandle, // fee-claim handle (x/github/discord); field name kept as `xHandle` for ABI stability
uint256 wethSeeded // always 0 — launches are single-sided/seedless; retained for ABI stability
)To confirm any token is a genuine ZeroHood launch: call InstantPoolFactory.tokenIndex(token) — 0 means not one of ours; any non-zero value is its 1-based index in launches. getLatest(n) returns the n most recent launches with full metadata for a backfill.
The profile image, website, X and Telegram are all in the event log itself — decode them straight from the Launched data, no IPFS-only, no external API, no follow-up call. Field → display mapping:
imageURI → profile image (https:// or ipfs://, always present)
website → website link (url, "" if unset)
twitter → X / Twitter link (url, "" if unset)
telegram → Telegram link (url, "" if unset)
name / symbol / description → token identityWatch this one event on the factory:
topic0 (verified against a live emitted event):
0xaab7db13ef23b7916e432d22cf716aebaff1644c405a4632fac716da46e9520e4. Single-sided liquidity model
At launch the factory mints the full 1B supply and deposits all of it into the v4 pool as a single-sided, token-only liquidity position (0 WETH), spread across a wide price range that starts at a low market cap (~$2,700-equivalent). Buyers supply the WETH as they buy; sellers get WETH back. Functionally it is a bonding curve implemented as one concentrated Uniswap v4 range.
Why it's done this way:
- Launch costs only gas — there is no liquidity for the creator to fund.
- Deep from block one — the whole supply backs the curve, so a ~$90 buy is roughly ~3% price impact, not 50%.
- No hard revert on size — the range is wide enough that a buy of any size fills; larger buys just move price more.
You can verify the single-sidedness directly: the v4 PoolManagerholds ~100% of a fresh launch's token supply and ~0 WETH until the first buy. The pool is a completely standard Uniswap v4 pool — fee 10000 (1%), tickSpacing 200, hooks = address(0) — so nothing ZeroHood-specific is needed to price or route it once discovered.
5. Anti-snipe max-wallet window
For 15 minutes after launch, no non-exempt wallet may hold more than 2% of total supply (20,000,000 tokens). After the window it lifts permanently. This is enforced inside the token itself — every transfer checks it — so it applies to swaps and direct transfers alike, and cannot be bypassed.
// on the launched token (LaunchToken):
maxWalletAmount() // uint256 — the per-wallet cap (2% of supply), or type(uint256).max if disabled
restrictionEndsAt() // uint64 — unix timestamp the window ends (0 if disabled)
restrictionActive() // bool — true while block.timestamp < restrictionEndsAt
// a transfer that would push a non-exempt wallet over the cap reverts:
error MaxWalletExceeded();The window is timestamp-based, not block-number-based — deliberate, because Robinhood Chain is an Arbitrum Orbit L2 where block.numberreturns the L1 (Ethereum) block number, not this chain's own count. The cap and duration are set at deploy and are immutable— there is no owner function to change or extend them. The v4 PoolManager (and the factory itself) are exempt so the initial liquidity mint isn't blocked by its own cap.
6. Trading a launched token
Because each launch is an ordinary Uniswap v4 pool (token / WETH, fee 10000, tickSpacing 200, no hooks) on the canonical PoolManager, you price and trade it with the standard v4 tooling — quote via the v4 Quoter, swap via the Universal Router. No ZeroHood-specific contract is involved in a trade at all; only discovery (see Detecting a ZeroHood launch above) is ZeroHood-specific.
The pool pairs with WETH, but the ZeroHood UI lets people trade in the chain's native ETH directly — nobody has to hold or think about WETH. A buy prepends a Universal Router WRAP_ETH command (the attached msg.value is wrapped to WETH inside the router, then swapped for the token), and a sell appends UNWRAP_WETH (the WETH out of the swap is unwrapped and paid back to the trader as native ETH). Integrators are free to trade the WETH pair directly instead; both hit the exact same pool.
Trading fees accrue in the pool. Anyone can pull them into the claimable escrow at any time by calling FeeCollectorVault.collectFees(token)(permissionless) — it splits collected fees 50/50 between the protocol treasury and the creator's claim key, and never touches the underlying liquidity (see Permanent liquidity lock below).
7. Permanent liquidity lock
The LP position NFT for every launch is minted straight to FeeCollectorVault and stays there forever. The vault's ABI has no function anywhere capable of decreasing liquidity, burning, or transferring the position out — the only thing it can ever do with a position is collect the trading fees it earned. There is no owner override, no pause, no emergency exit.
Verify the lock yourself: on the v4 PositionManager, ownerOf(tokenId) for any launch always returns the FeeCollectorVault address in Contract addresses — an immutable contract with no withdrawal path. No rug is possible from launch second one.
Every launch's LP position NFT is owned by a single immutable holder with no withdraw/decrease/ transfer path — functionally equivalent to a burn, but the position stays fee-collectible. A scanner can safely mark liquidity as locked/burntwhen a token's v4 position is owned by:
The vault has no owner, no upgrade path, and no function that can reduce or move a position — only collectFees(). So "liquidity locked" is provable purely from the position's owner being this address.
8. Creator fee claims (X / GitHub / Discord)
At launch the creator directs their 50% fee share to their own wallet or to a handle on X, GitHub, or Discord. The destination is baked into an on-chain claimKey:
// LaunchFeeEscrowV2:
walletClaimKey(address wallet) // keccak256("wallet", wallet)
socialClaimKey(string platform, string handle) // keccak256("social", platform, handle)
// platform is one of "x" | "github" | "discord"; handle is lowercased, no @A social-delegated fee share is claimable the moment that person logs into ZeroHood with the matching account — even if the token was launched before they ever heard of it. Ownership is proven by OAuth at claim time; the escrow only pays out on a relayer-signed authorization tied to the verified identity. Fees are tracked per-(claimKey, currency), so a pool that has earned in both WETH and the token accrues both claimable independently.
9. Token Locker
TokenLocker (address in Contract addresses) is a standalone, trustless time-lock vault for any ERC-20 on Robinhood Chain — unrelated to launches. Anyone locks tokens until a future timestamp; only the lock's creator can withdraw, and only once that time passes.
lock(address token, uint256 amount, uint64 unlockTime) returns (uint256 lockId)
withdraw(uint256 lockId) // reverts unless msg.sender == owner AND block.timestamp >= unlockTime
extend(uint256 lockId, uint64 newUnlockTime) // can only push LATER, never shorten
getUserLocks(address) / getLock(uint256) / totalLocks()
event Locked(uint256 indexed lockId, address indexed owner, address indexed token, uint256 amount, uint64 unlockTime);
event Withdrawn(uint256 indexed lockId, address indexed owner, address indexed token, uint256 amount);
event Extended(uint256 indexed lockId, uint64 newUnlockTime);Guarantees: no owner/admin/pause/rescue of any kind exists on the contract; a lock can never be shortened or released early by anyone (including its creator); withdraw is double-gated on owner + time; reentrancy-guarded with effects-before-interaction; and it records the actual amount received (fee-on-transfer safe). It uses block.timestamp, notblock.number, for the same L2 reason as Anti-snipe max-wallet window.
Detecting a lock for a specific token (for scanners):
- Filter
Lockedevents onTokenLockerwhere the indexedtokentopic equals the token address —topic0 = 0x8304b8c1ad220f367b10eb7062c3c2e5d5568a59cad020b216ff3d168766af17. - Sum
amountacross matches; subtract any whoselockIdalso has a matchingWithdrawnevent (topic0 = 0xe5df19de43c8c04fd192bc68e484b2593570925fbb6ad8c07ccafbc2aa5c37a1) — that's the token's current locked balance. - Or skip event replay entirely: call
getLock(lockId)directly — it returns{owner, token, amount, unlockTime, withdrawn}in one read.
Live example (a real lock, locked then withdrawn after maturity — good for testing both paths):
locked: 0xe0c2bad2…9f6 · withdrawn: 0x976154cf…4f0
10. Security properties
- No rug: pool liquidity is locked in an immutable vault with zero withdrawal path (see Permanent liquidity lock).
- No presale / no team allocation: 100% of supply goes into the pool at launch; the creator gets a fee share, never a supply share.
- Permissionless launch, self-custody: the creator is bound to
msg.senderon-chain; no relayer signs or holds anything for a launch or trade. - No caller-controlled fund pull: the WETH side of the mint is hardcoded to 0, so no launch parameter can make the factory pull WETH from anywhere — a bad parameter can at worst make a bad pool for the caller's own token.
- Anti-snipe: 2%-of-supply per-wallet cap for 15 minutes, enforced in-token, timestamp-based (see Anti-snipe max-wallet window).
- Standard token: LaunchToken is a plain fixed-supply ERC-20 with EIP-2612 permit and no transfer tax — the anti-snipe cap is the only non-standard transfer rule, and it expires.
- Limited owner power: the factory owner can only redirect the protocol's own 50% fee cut (
setTreasury) — it can never touch pool liquidity, creator fees, or user tokens.
11. Verifying a token yourself
End-to-end, no trust required:
- Call
InstantPoolFactory.tokenIndex(token)— non-zero confirms it's a ZeroHood launch. - Read the
Launchedevent (see Detecting a ZeroHood launch) for its metadata andtokenId. - On the v4
PositionManager, checkownerOf(tokenId)==FeeCollectorVault— proves liquidity is locked. - Query the v4 pool (
token/WETH, fee 10000, tickSpacing 200, hooks 0) on thePoolManagerto price it. - Optionally read
token.restrictionActive()/maxWalletAmount()to see if the anti-snipe window is still open.
Explorer for spot-checking any address: https://robinhoodchain.blockscout.com
community & support
indexer/scanner integrating ZeroHood? reach out on X or Telegram.