Launching an index
Launching is permissionless — anyone can create an index token from the app or by calling the factory directly. Every parameter below is fixed forever at launch, so choose deliberately.
From the app
The Create wizard walks through four steps:
- Basics — name, symbol, total supply.
- Basket — pick 1–16 tokenized stocks/ETFs from the governance allow-list (search box included). On testnet these are the 18 mock stocks (Mag 7 + AVGOx, COINx, MSTRx, AMDx, NFLXx, PLTRx, ORCLx, CRCLx, SPYx, QQQx, SOXXx); on mainnet the 25 official Robinhood Chain tokenized equities.
- Fees — the buy fee and sell fee (each ≤ 10%), plus the "RFV backing vs holder distribution" slider: how the 90% non-protocol share of every fee splits between the redeemable USDG floor and stock dividends (0–90% RFV; the protocol's 10% is fixed and shown separately).
- Review — confirm and submit. One transaction deploys everything.
What one launch deploys
IndexFactory.createIndex(cfg) performs, atomically:
- Clones the immutable
IndexTokenimplementation (EIP-1167 minimal proxy) and initializes it with your config — the initializer validates the fee cap, basket size, allow-list membership, duplicates, and rejects the reserve asset or the token itself as basket members. - Deploys a dedicated
IndexTreasury(the RFV vault) bound to your token. - Mints supply: 1% → protocol treasury, 99% → you (the caller is always recorded as creator — it can't be spoofed).
- Forwards the native launch fee (if
FeeRegistry.launchFeeWei > 0). - Emits
IndexCreatedwith the full config (includingrfvShareBps), which the indexer picks up.
Launching from a contract or script
IndexConfig memory cfg = IndexConfig({
name: "Mag Seven",
symbol: "MAG7",
creator: address(0), // overwritten with msg.sender by the factory
totalSupply_: 1_000_000e18,
buyFeeBps: 300, // 3% buy fee (max 1000)
sellFeeBps: 300, // 3% sell fee (max 1000)
stocks: stocks, // 1..16 allow-listed stock token addresses
distributionMode: 0, // reserved; keep 0
rfvShareBps: 1500 // 15% of fees → RFV floor (0..9000)
});
(address token, address treasury) =
IndexFactory(FACTORY).createIndex{value: launchFee}(cfg);
Constraints enforced on-chain (reverting errors in parentheses):
| Parameter | Constraint |
|---|---|
buyFeeBps / sellFeeBps | ≤ 1000 (10%) — immutable after launch |
stocks | 1–16 entries (EmptyBasket / BasketTooLarge), no duplicates (DuplicateAsset), each on the FeeRegistry allow-list (AssetNotAllowed), never the reserve asset or the token itself |
rfvShareBps | 0–9000 (RfvShareTooHigh) — immutable |
totalSupply_ | > 0 (ZeroAmount) |
msg.value | ≥ FeeRegistry.launchFeeWei (InsufficientLaunchFee) |
After launch: make it tradable
The token starts fee-inert — fees only apply to trades against a registered AMM pair:
- Seed liquidity. Create an index/USDG pool on the chain's Uniswap v2-style DEX and add liquidity (you received 99% of supply).
- Register the pair. Call
setAmmPair(pair, true)(creator-gated). The contract validates it is a genuine pool for this token (token0/token1check) and marks it dividend-excluded so LP balances never soak up holder dividends.
Register before (or immediately after) seeding
The pair is dividend-excluded at registration and reserves are reconciled — but registering promptly keeps distribution accounting clean from the first trade.
- Trade. From here the fee lifecycle runs on its own: fees accrue, anyone converts, holders claim.
Choosing the RFV split
rfvShareBps | Character |
|---|---|
0 | Pure dividend index — the full 90% buys stocks for holders |
1500 (default) | 15% floor / 75% dividends — the classic $INDEX-style profile |
9000 | Pure RFV index — all fees deepen the redemption floor; the stock-buy loop is skipped entirely |
There is no wrong answer — it is a product decision about whether your index rewards holding via income (dividends) or holding via backing (a rising floor).