# Robin Hook agent skill

Read a Robin Hook token's rules, quote, buy and sell it on the bonding curve or in its Uniswap v4 pool,
launch a token, and claim what the hook owes you. No account, no API key: every step is a chain read or a
signed transaction. Site: https://robinhook.lol. A token's identity is its address plus chain 4663.

## Chain

- Robinhood Chain, chain id 4663, native ETH (18 decimals)
- Public RPC: https://rpc.mainnet.chain.robinhood.com
- Explorer: https://robin.etherscan.io (all contracts source-verified)
- Quotes: ETH (0x0), USDG `0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168` (6 dec), ecosystem coins, Robinhood stock tokens

## Addresses (generated from script/v2-state.json)

- RobinHookV2 (the hook): `not deployed yet`
- HookLaunchpadV2: `not deployed yet`
- RobinHookRouterV2: `not deployed yet`
- HookLensV2: `not deployed yet`
- HookModuleRegistry: `not deployed yet`
- HookTokenFactoryV2: `not deployed yet`
- QuoteRegistry: `not deployed yet`
- RobinHookZap: `not deployed yet`
- RobinHookLimitOrders: `not deployed yet`
- BlueprintRegistryV1 (hook marketplace): `not deployed yet`, RoyaltyModule: `not deployed yet`
- Uniswap v4 PoolManager: `0x8366a39CC670B4001A1121B8F6A443A643e40951`, StateView `0xF3334192D15450CdD385c8B70e03f9A6bD9E673b`, V4Quoter `0x8Dc178eFB8111BB0973Dd9d722ebeFF267c98F94`
- Official token HOOK: `not launched yet`

0 modules are deployed; `GET /api/hooks/catalog` lists each with id, address, status and config ABI.

## Read a token

```
launchpad.getLaunch(token) view returns (Launch)  // reverts if not a Robin Hook v2 launch
  // creator, quote (0x0 = ETH), creatorFeeBps, reserve, target, tokensSold, complete, graduated, ...
lens.launchesPage(offset, limit) view returns (LaunchView[])  // newest first
lens.modulesOf(token) view returns (address[] modules, uint16[] caps)  // frozen at launch, dispatch order
launchpad.poolKey(token) view returns (PoolKey)  // {currency0, currency1, fee: 0x800000 dynamic, tickSpacing: 60, hooks}
launchpad.poolId(token) view returns (bytes32)
hook.poolInfo(poolId) view returns (PoolView)  // token, quote, creator, quoteIs0, creatorFeeBps, baseFeePips, modules, moduleCaps
```

Match module addresses against the catalog to get names and config. `graduated == false`: trade on the
curve. `graduated == true`: trade in the pool. Token transfers are locked until graduation.

## Quote

Curve (module cuts included; not `view`, call with `eth_call` / viem `simulateContract`):

```
lens.quoteBuy(token, amountIn, trader) returns (Quote)
lens.quoteSell(token, tokenAmount, trader) returns (Quote)
// Quote { out, used, inCut, outCut, extraFee, wouldRevert, reason }
```

If `wouldRevert` is true a module or the curve guard refuses the trade; `reason` holds the revert data.

Pool: Uniswap `V4Quoter.quoteExactInputSingle({poolKey, zeroForOne, exactAmount, hookData: 0x})` via
`eth_call`. A buy is `zeroForOne == quoteIs0`. Empty hookData quotes as an anonymous trader;
trader-specific modules (pots, crowns, caps) can differ for your address.

Or `GET /api/tokens/<token>?buy=<raw quote>&sell=<raw tokens>&trader=<you>`.

## Buy and sell on the curve (not graduated)

```
launchpad.buy(token, minTokensOut) payable  // ETH curves, value = amountIn
launchpad.buyWithQuote(token, amountIn, minTokensOut)  // ERC-20 quote, approve launchpad first
launchpad.buyWithData(token, amountIn, minTokensOut, referrer, extra) payable  // value = amountIn on ETH, else 0
launchpad.sell(token, tokenAmount, minQuoteOut)
launchpad.sellWithData(token, tokenAmount, minQuoteOut, extra)
```

`extra` is opaque per-trade data for modules (e.g. an allowlist proof); pass `0x` if unused.
The buy that fills the curve graduates the token into the pool.

## Buy and sell in the pool (graduated)

```
router.buy(token, amountIn, minTokensOut, referrer, deadline, extra) payable returns (uint256 out)
  // ETH pools: value = amountIn; ERC-20 quote: approve router, value 0
router.sell(token, amountIn, minQuoteOut, deadline, extra) returns (uint256 out)  // approve router for the token
```

hookData layout: the router passes `abi.encode(address trader, address referrer, bytes extra)` with
trader = msg.sender. The hook trusts hookData only from this router; any other caller trades as anonymous
(pots, crowns and referrals then skip you). Direct PoolManager / Universal Router swaps must be exact-input
with price limit `MIN_SQRT_PRICE+1` (zeroForOne) or `MAX_SQRT_PRICE-1`, else `ExactOutputBlocked` /
`PartialFillNotAllowed`.

## Launch

```
launchpad.launch(LaunchArgs) payable returns (address token)
LaunchArgs {
  string name;  // 1..32 bytes
  string symbol;  // 1..12 bytes
  Metadata meta;  // {description <=500 bytes, image <=300 bytes, website, twitter, telegram}
  address quote;  // 0x0 = ETH, else an asset allowed in QuoteRegistry
  CoreConfig core;  // {uint16 creatorFeeBps <=1000, uint24 baseFeePips <=100000}
  CurveGuard guard;  // {uint32 guardBlocks <=1200 (L1 blocks, ~12 s), uint96 maxBuyPerBlock, uint16 snipeTaxBps <=2500}
  uint32[] moduleIds;  // registry ids, <=8, active, no shared conflict group
  bytes[] moduleConfigs;  // abi.encode of each module's config tuple (catalog: meta.config.abi)
  uint256 devBuy;  // creator's first buy, quote units
  uint256 minTokensOut;
}
```

value = `launchpad.creationFee()` (ETH) + `devBuy` on ETH curves; ERC-20 quotes: value = creationFee,
approve the launchpad for devBuy. Modules are frozen at launch and can never be changed.

## Launch from a marketplace blueprint

```
blueprints.page(offset, limit) view returns (uint32[] ids, Blueprint[])  // author, royaltyBps, profile, hidden, name, uri
blueprints.specOf(id) view returns (bytes)  // abi.encode(uint32[] moduleIds, bytes[] moduleConfigs, uint16 creatorFeeBps, uint24 baseFeePips)
```

Profile 0, not hidden: copy the spec into `LaunchArgs`. If `royaltyBps > 0` (max 0.5% of every trade, to the
author) append RoyaltyModule's id, config `abi.encode(uint32 blueprintId, address author, uint16 bps)` exactly
as registered; these become launchable once the royalty module is registered.

Pools for existing tokens (/pools) are coming soon: not deployed, no addresses yet.

## Claim

```
hook.claimable(account, currency) view returns (uint256)  // currency 0x0 = ETH
hook.claim(currency, to)  // module rewards, pots, creator fees in the pool
launchpad.claimable(account, quote) view returns (uint256)
launchpad.claim(quote) / launchpad.claimTo(quote, to)  // curve creator fees, locked-LP fees
launchpad.collectLpFees(token)  // anyone: moves the locked position's LP fees to claims
```

## Public JSON (GET, CORS *, HTTP 503 on read failure)

- `/api/hooks/catalog`: contracts, every module, fee model
- `/api/protocol-stats`: launches, graduated (lifetime trades and volume are marked unavailable)
- `/api/tokens?sort=new|mcap`, `/api/tokens/<address>`
- `POST /api/v1/tx/trade` `{token, side, amount, from, slippageBps?, referrer?}` and `POST /api/v1/tx/launch`: ordered unsigned steps `{to, data, value, description}` to sign and send; amounts are decimal strings in whole units (guide: /docs/integrate)
- `/api/scan/<hook | token | poolId>`: HookScan report (screening, not an audit)
- Docs: https://robinhook.lol/docs/api

## Safety rules

- Check the token address on chain 4663 with `launchpad.getLaunch`; names and symbols are not unique.
- Read the modules before trading: some cap buys or holdings, block sells for a while, or tax snipers.
- Always quote first and set `minTokensOut` / `minQuoteOut` from the quote minus your slippage; never 0.
- Exact input only. Never send a swap with a partial price limit.
- Simulate (`eth_call`) every transaction before signing; a module can refuse a trade.
- Official sources only: robinhook.lol and x.com/robinhooklol. HOOK is `not launched yet`. Robin Hook never DMs first and never asks for a seed phrase.
