Architecture
HoodETF is three cooperating layers on top of Robinhood Chain: contracts, a backend indexer + API, and a web app. Only the contracts hold funds or enforce rules; everything off-chain is convenience and presentation.
System overview
Robinhood Chain (chain id 4663)
┌───────────────────────────────────────────────────────────────┐
│ Whitelist ──► BasketFactory ──clones──► Basket Basket Basket │
│ │ ▲ │
│ OracleLib (Chainlink reads) │ mint / redeem │
│ HoodZapRouter ─► HoodV4SwapAdapter ─► Uniswap v4
└───────────────────────────────────────────────────────────────┘
▲ reads (logs, eth_call) ▲ tx
│ │
┌──────────┴───────────┐ ┌───────────┴───────────┐
│ Backend (Node/Hono) │ │ Web app (Next.js) │
│ indexer · NAV worker │◄── REST /v1 ──► │ app.hoodetf.org │
│ leaderboard · zapper │ │ wallet + SIWE │
└──────────────────────┘ └───────────────────────┘
Layer 1 — Smart contracts
The trust boundary. All value and rules live here.
- Whitelist — governance-owned registry mapping each allowed token to its Chainlink feed, staleness limit, and decimals.
- OracleLib — a library that reads a Chainlink feed with staleness + sequencer-uptime guards, returning
stale=trueinstead of reverting. - Basket — the vault. Holds the constituent tokens, issues ERC-20 shares, and implements in-kind mint/redeem, zap-mint, fees, and NAV.
- BasketFactory — clones, seeds, and initializes new baskets atomically, and registers them.
- HoodZapRouter — atomic one-click buy/sell: pulls USDG, swaps through allowlisted venues, mints/redeems in one transaction.
- HoodV4SwapAdapter — a plain-ERC20 swap venue that trades directly against Uniswap v4 (single-hop and USDG→ETH→token multi-hop).
Baskets are immutable once deployed: constituents and fees are fixed, and there is no function that lets anyone withdraw another holder's assets.
Layer 2 — Backend (indexer + API)
A Node/TypeScript service (Hono + viem + BullMQ + Postgres + Redis) that:
- Indexes
BasketCreatedand mint/redeem events into Postgres. - Computes NAV on a schedule: reads each basket's on-chain balances and Chainlink prices, writes NAV snapshots, and refreshes per-constituent weights.
- Ranks baskets by return over 24h / 7d / 30d / inception windows into Redis sorted sets (the leaderboard).
- Builds zap quotes — splits a USDG amount across constituents by on-chain value, finds the best route per leg through the venue adapters, and returns a ready-to-submit router transaction.
- Serves all of this to the web app over a private REST API.
The backend never holds funds or keys that can move a user's assets. If the backend is down, the app degrades (stale/less data) but the contracts keep working — in particular, redemption is entirely on-chain.
Layer 3 — Web app
A Next.js app served on three host-routed surfaces from one deployment:
hoodetf.org— marketing site.app.hoodetf.org— the dapp: discover, basket detail, portfolio, create wizard, trade.admin.hoodetf.org— operator dashboards (monitoring, whitelist, venues).
Wallet connection uses RainbowKit; authenticated features use Sign-In With Ethereum (SIWE). On-chain numeric amounts are represented as raw integer strings (see the wire-format note in Core concepts), which the client divides down for display.
Chain
Everything runs on Robinhood Chain, an Arbitrum-Orbit L2 with chain id 4663. The stablecoin used for one-click zaps is USDG (6 decimals). Deployed contract and token addresses are on the Deployed addresses page.