Fourmate docs
Your liquidity companion for Uniswap v4 on Robinhood Chain.
What Fourmate is
Inspect pool mechanics, understand hook permissions, and add liquidity through a guided, wallet-controlled flow. Fourmate helps you see what you’re signing and follow what happens next.
- Inspect — pool state from StateView, core reserves from ReservesLens, hook permission bits decoded from the address, verification status from Sourcify and the explorer, admin probes that only count when the contract answers.
- Add Liquidity — a guided, wallet-controlled flow that mints or increases a Uniswap v4 position with your own tokens.
- Manage — positions owned by your wallet with range status, composition and uncollected fees; increase, remove, collect, burn.
- Ask Fourmate — an assistant grounded in the same tool results, with sources and explicit unknowns.
“Liquidity Assist” means helping you deploy your own capital. Fourmate supplies no capital, guarantees no liquidity depth, moves no token price and promises no return. There is no Fourmate token, no fee mechanism in this build, no audit claim and no partnership claim.
Networks
This deployment serves Robinhood Chain (chain id 4663, Mainnet). Network facts come from docs.robinhood.com/chain/connecting and were cross-checked with eth_chainId on three public endpoints.
- Mainnet (4663) — verified Uniswap v4 deployment; every flow is enabled.
- Testnet (46630) — developers.uniswap.org/deployments.json lists no Uniswap v4 contract for this chain; the app shows an honest shell with every transaction path disabled. To enable it, a verified deployment must be published and added to
src/config/integrations.ts, thenpnpm verify:integrationsmust pass. - Local fork (31337) — an Anvil fork of mainnet used by the execution tests (
pnpm chain:fork,pnpm flow:fork); labelled as development everywhere.
Support policy
Fourmate prepares liquidity transactions only for pools whose hook cannot intercept deposits or withdrawals: pools without a hook, and pools whose hook only acts on swaps, donations or initialisation.
Pools whose hook runs on add/remove liquidity, or that use custom accounting (return-delta flags), are shown for inspection but their transaction paths stay disabled until that behaviour is integrated and tested.
Inspection decodes declared permissions and verification status. It is not a security audit and never a safety verdict.
- No hook — supported.
- Swap-phase hook (only initialize / swap / donate callbacks) — supported; the hook still shapes swaps and fees.
- Liquidity hook (before/after add or remove liquidity) — view only: it can reject, gate or delay deposits and withdrawals.
- Custom accounting (return-delta flags on liquidity) — view only: it can change what a deposit costs or a withdrawal pays.
- A hook address without bytecode is view only regardless of its flags.
How a deposit works
- Connect an injected wallet (EIP-6963). Fourmate reads through its own relay and never holds keys.
- Confirm the network; a wallet on another chain is blocked from every write.
- Choose a supported pool (search by symbol, token address or pool id).
- Review the pool and hook inspection.
- Enter amounts. The other side follows the range at the current price; nothing is swapped.
- Choose a range: presets (not recommendations), price inputs in either direction, ± tick steps. Ticks snap to the pool’s spacing; invalid ranges are rejected with the protocol’s own rules.
- Review the composition: liquidity obtained, exact amounts charged (rounded up as the PoolManager does), what stays in your wallet.
- Preview: the server reads balances and both allowance layers, builds the steps, binds them to your account and chain, and the preview expires after 2 minutes.
- Simulate: every step runs through
eth_simulateV1from your account (fallback: per-stepeth_call); reverts are decoded against the verified ABIs. - Approve and submit: ERC-20 → Permit2 approval (exact by default), Permit2 → PositionManager allowance (time-boxed, 1 h by default), then
modifyLiquidities. Each step is re-validated in the browser (chain, account, expiry, allow-list) right before the wallet is asked. Native ETH is sent asmsg.valueand the unused part returned bySWEEP. - Receipts are polled every second; a hash is persisted the moment the wallet returns it; replaced and reverted transactions are told apart; an approval that confirmed while the deposit did not is shown exactly like that.
- The minted token id is read from the receipt and the position opens in Manage.
Slippage (0.5% default, 0.01–5%) bounds the amounts the PositionManager may take or must pay; the deadline (20 min default) reverts late transactions. Service fee: none; no fee mechanism exists in this build, every preview shows 0 and no transaction carries one.
Positions and fees
Positions are read from the PositionManager (getPoolAndPositionInfo, getPositionLiquidity, ownerOf) and StateView (getSlot0, getFeeGrowthInside, getPositionInfo with the PositionManager as owner and the token id as salt). Uncollected fees are liquidity × Δ feeGrowthInside / 2¹²⁸, exactly as Position.update settles them. Token amounts are the amounts a full withdrawal would pay at the current price (rounded down). Nothing is estimated from wallet balances.
The position token is not enumerable. Discovery uses the explorer’s NFT index, the PositionManager’s Transfer events to your address (adaptive, time-budgeted, newest first) and ids the browser remembers from its own mints; every candidate is confirmed with ownerOf. Coverage is stated with each list. Removing all liquidity does not burn the token; burning is a separate, explicit action.
Pool discovery
Robinhood Chain holds over a million Uniswap v4 pools (1,079,019 Initialize events were counted on 2026-10-25 UTC, about 707,000 of them without a hook), so no complete listing is served. The index is the union of verified-pair candidates (registry tokens × the four standard fee tiers, hookless), pools initialised in the recent window (an adaptive log scan with a time budget) and pools opened on demand. Any pool opens by id (PositionManager key store, then an Initialize lookup) or by token address (Initialize events on both currency slots). Every listing says what it covers and never claims completeness.
Ask Fourmate
The assistant is a server-side Anthropic Claude integration (the key never reaches the browser). It can call the same functions the pages use (network status, pool inspection, pool search, position reads, history, range explanation, deposit planning, the preview on screen) and must cite tool results with their block or timestamp, label observations versus explanations versus estimates, and name what it could not verify. Token names and contract names are wrapped as untrusted data. It cannot build calldata, sign, submit or ask for keys; its only actions are buttons that open deterministic flows you review in your wallet. Without ANTHROPIC_API_KEY it shows an honest unavailable state and the deterministic explanations still run — no canned “AI” replies.
The $4MATE token
$4MATE is the Fourmate token on Robinhood Chain (chain 4663). Its contract address is published on the landing page and announced first on @fourmaterh_; until then the site says Soon and no address claiming to be $4MATE is ours. Publishing is a verified step: pnpm token:set 0x… checks the EIP-55 checksum, the chain id, bytecode and the ERC-20 reads (symbol, name, decimals, total supply) before writing the address into src/config/token.ts; the page then shows the address with a copy button, an explorer link and the facts that were read. The site never shows a price, market cap or holder count for the token, and Fourmate never asks anyone to buy it. Current address: 0xd47760937E8BE87222F0ffcDE0006Eb3bCF7D393 (published 2026-10-26).
Data honesty
- Liquidity (L) is a pool unit and is never labelled TVL or dollars.
- USD values appear only with a dated price (Chainlink ETH/USD and USDG/USD on chain, DefiLlama by address) and say when one side is unpriced.
- Token identity is verified only for the hand-checked registry; everything else is “unverified metadata”, with look-alike symbols flagged.
- Hook permissions are facts; their economic meaning is interpretation; unreadable behaviour is unknown. No safety score, audit badge or verdict exists in the product.
- Every figure carries the block it was read at; stale data is labelled.
Capability matrix
Verified integrations
Every address below is pinned in src/config/integrations.ts and re-checked by pnpm verify:integrations (bytecode, wiring, Sourcify, deployments.json). Primary source: https://developers.uniswap.org/deployments.json (v1.0.0, generated 2026-10-16; records filtered by chainId 4663, tier labs-supported, status active; no record exists for chain 46630).
Robinhood Chain JSON-RPC
operational- official: https://rpc.mainnet.chain.robinhood.com
- publicnode: https://robinhood-rpc.publicnode.com
- drpc: https://robinhood.drpc.org
- operationalRead chain state (calls, balances, receipts)
- operationalEvent scans (pool initialisations, position transfers, liquidity changes)— Adaptive windows with a time budget; partial coverage is reported, never hidden.
- operationaleth_simulateV1 multi-step simulation— Falls back to eth_call per step where the method is unavailable.
- operationalSame-origin read relay for browsers— Read methods only; the wallet broadcasts transactions itself.
Sources (3)
- https://docs.robinhood.com/chain/connecting/ (chain id 4663, public endpoints)
- eth_chainId → 0x1237 on all three endpoints (2026-10-25 UTC)
- eth_getLogs: the official node serves 5M-block windows capped at 10,000 matched logs; publicnode refuses log scans ("Archive requests require a personal token"); dRPC free plan caps ranges at 10,000 blocks
Blockscout explorer + API
operational- site: https://robinhoodchain.blockscout.com
- api: https://robinhoodchain.blockscout.com/api/v2
- operationalToken metadata and verification status— Key-free; cold addresses can take tens of seconds; a 5xx is reported as unavailable.
- operationalSmart-contract verification status (hooks, tokens)
- operationalIndexed ERC-721 holdings (first pass of position discovery)
- operationalExplorer links for every address, transaction and block
Sources (2)
- Explorer host listed in docs.robinhood.com/chain/connecting
- /api/v2/addresses/{a} answered for PoolManager, PositionManager and StateView (verified: true) on 2026-10-25 UTC
Sourcify verified sources
operational- v2: https://sourcify.dev/server/v2/contract/4663/{address}
- operationalSource-verification status of hook contracts
Sources (1)
- PositionManager match 46997905 (runtime match, 2026-09-01), PoolManager match 47290695 (creation + runtime match, 2026-09-08); action constants, parameter layouts and error lists in this app were read from those sources on 2026-10-25 UTC
Multicall3
operational- Multicall3 0xcA11bde05977b3631167028862bE2a173976CA11canonical deployment · eth_getCode → 3,808 bytes at the canonical address (2026-10-25 UTC); aggregate3 answers
- operationalBatched reads (aggregate3) in bounded waves at one pinned block
Sources (2)
- https://www.multicall3.com (canonical address on every chain)
- eth_getCode on chain 4663
Uniswap v4 (official Labs deployment)
operational- PoolManager 0x8366a39CC670B4001A1121B8F6A443A643e40951v4-core 56928a9, solc 0.8.26 · Sourcify match: https://sourcify.dev/server/v2/contract/4663/0x8366a39CC670B4001A1121B8F6A443A643e40951; eth_getCode 24,009 bytes; Blockscout verified
- PositionManager 0x58daec3116aae6D93017bAAea7749052E8a04fA7v4-periphery (deployments.json ref 56928a9), solc 0.8.26 · Sourcify match: https://sourcify.dev/server/v2/contract/4663/0x58daec3116aae6D93017bAAea7749052E8a04fA7; eth_getCode 23,877 bytes; Blockscout verified; poolManager()/permit2() wired (checked by verify:integrations)
- PositionDescriptor 0x9639443158E8C5efa35Bd45287bf2EFfd3D8dC06v4-periphery · https://developers.uniswap.org/deployments.json (v1.0.0, generated 2026-10-16; records filtered by chainId 4663, tier labs-supported, status active; no record exists for chain 46630)
- StateView 0xF3334192D15450CdD385c8B70e03f9A6bD9E673bv4-periphery src/lens/StateView.sol · Sourcify match: https://sourcify.dev/server/v2/contract/4663/0xF3334192D15450CdD385c8B70e03f9A6bD9E673b; eth_getCode 3,531 bytes; Blockscout verified
- V4Quoter 0x8Dc178eFB8111BB0973Dd9d722ebeFF267c98F94v4-periphery src/lens/V4Quoter.sol · https://developers.uniswap.org/deployments.json (v1.0.0, generated 2026-10-16; records filtered by chainId 4663, tier labs-supported, status active; no record exists for chain 46630); eth_getCode 6,118 bytes
- ReservesLens 0x0000001b173C3bbF3984D417d8614E3eed34865Bv4-periphery src/lens/ReservesLens.sol (ref b08eb66) · https://developers.uniswap.org/deployments.json (v1.0.0, generated 2026-10-16; records filtered by chainId 4663, tier labs-supported, status active; no record exists for chain 46630); eth_getCode 14,142 bytes
- UniversalRouter v2.1.2 0x204FAca1764B154221e35c0d20aBb3c525710498universal-router 802fe4c · https://developers.uniswap.org/deployments.json (v1.0.0, generated 2026-10-16; records filtered by chainId 4663, tier labs-supported, status active; no record exists for chain 46630)
- WETH9 (aeWETH) 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73Arbitrum-style WETH9 behind a proxy · PositionManager.WETH9() returns this address (checked by verify:integrations); symbol() WETH, decimals 18
- operationalPool state (StateView slot0 + liquidity), core reserves (ReservesLens), hook permission decoding
- operationalPool discovery from Initialize events (verified pairs + recent window + on-demand lookups)— The index is not a complete list of every pool ever initialised; coverage is stated on every listing.
- operationalPosition inventory and uncollected fees (PositionManager + StateView fee growth)
- operationalAdd liquidity (MINT_POSITION / INCREASE_LIQUIDITY + SETTLE_PAIR, native via SWEEP)— Only for hookless and swap-phase-hook pools; every other pool is view-only.
- operationalRemove liquidity, collect fees, burn (DECREASE_LIQUIDITY / BURN_POSITION + TAKE_PAIR)
- unavailableSwap quotes (V4Quoter)— Not used: Fourmate never swaps on the user's behalf.
- unavailableSwap execution (Universal Router)— Not integrated by design; the address is listed for reference only.
Sources (3)
- https://developers.uniswap.org/deployments.json (v1.0.0, generated 2026-10-16; records filtered by chainId 4663, tier labs-supported, status active; no record exists for chain 46630)
- Sourcify v2 matches for PoolManager, PositionManager, StateView (2026-10-25 UTC)
- eth_getLogs Initialize from block 9,070: 5,041 pools in the first 5M blocks alone (2026-10-25 UTC)
Permit2
operational- Permit2 0x000000000022D473030F116dDEE9F6B43aC78BA3permit2@1.0.0 (canonical) · https://developers.uniswap.org/deployments.json (v1.0.0, generated 2026-10-16; records filtered by chainId 4663, tier labs-supported, status active; no record exists for chain 46630); eth_getCode 9,152 bytes; PositionManager.permit2() returns it
- operationalAllowance reads (owner, token, spender)
- operationalTime-boxed approvals of the PositionManager (exact amount by default)— Two approvals per ERC-20: token → Permit2, then Permit2 → PositionManager. Both are shown with spender and scope.
Sources (1)
- https://developers.uniswap.org/deployments.json (v1.0.0, generated 2026-10-16; records filtered by chainId 4663, tier labs-supported, status active; no record exists for chain 46630)
Chainlink Data Feeds
operational- ETH / USD 0x78F3556b67E17Df817D51Ef5a990cDaF09E8d3A9EACAggregatorProxy, 8 decimals, 24 h heartbeat · docs.robinhood.com/chain/oracles-and-price-feeds + Chainlink reference-data directory; latestRoundData answers (verify:integrations)
- USDG / USD 0x61B7e5650328764B076A108EFF5fa7282a1B9aD2EACAggregatorProxy, 8 decimals · Chainlink reference-data directory feeds-robinhood-mainnet.json; latestRoundData answers (verify:integrations)
- directory: https://reference-data-directory.vercel.app/feeds-robinhood-mainnet.json
- operationalReference USD prices for ETH / WETH and USDG— Every valuation shows its source and age.
Sources (2)
- https://docs.robinhood.com/chain/oracles-and-price-feeds/
- Chainlink reference-data directory for Robinhood mainnet
DefiLlama coins API
operational- prices: https://coins.llama.fi/prices/current/{keys}
- operationalMarket USD prices by token address (missing prices stay missing)
Sources (1)
- chain slug "robinhood" (keys robinhood:<address>); probed by verify:integrations
Anthropic Claude (Ask Fourmate)
config-dependent- messages: https://api.anthropic.com/v1/messages
- config-dependentEvidence-grounded explanations of pools, hooks, ranges, positions and prepared actions— Without a key the assistant shows an honest unavailable state; the deterministic explanations stay available.
Sources (1)
- Server-side key ANTHROPIC_API_KEY; model from ANTHROPIC_MODEL
Configuration
See .env.example. Public variables (NEXT_PUBLIC_*) are baked into the client at build time: the network, the canonical site URL and project links (links that are not configured are not rendered). Server variables: the upstream RPC override, the log-scan endpoint, DoH pinning for blocked resolvers, index budgets and the Anthropic key, model and effort.
Limitations
- Pools whose hook runs on liquidity callbacks or uses custom accounting are view only until that behaviour is modelled and tested.
- No swap-assisted deposits: amounts are deposited as entered; the remainder stays in your wallet.
- Injected wallets only (no WalletConnect in this build); Permit2 allowances are set with transactions, not signatures.
- The pool index covers verified pairs, the recent window and on-demand lookups, not the full history.
- USD figures depend on third-party price sources and are shown with their age; many tokens have none.
- Testnet has no verified Uniswap v4 deployment; the fork-based execution tests stand in for a test environment.