Skip to main content

IndexFactory

contracts/src/index/IndexFactory.sol — the permissionless launchpad. One immutable singleton per chain; anyone can call createIndex.

createIndex

function createIndex(IndexConfig calldata cfg)
external payable
returns (address token, address treasury);

Atomically:

  1. Checks the registry isn't paused and the protocol treasury is wired.
  2. Requires msg.value ≥ FeeRegistry.launchFeeWei (InsufficientLaunchFee).
  3. Overwrites cfg.creator with msg.sender — creatorship can't be spoofed.
  4. Clones the immutable IndexToken implementation (EIP-1167) and deploys a fresh IndexTreasury(reserveAsset, token).
  5. Calls token.initialize(...), which validates everything and mints supply (1% protocol / 99% creator).
  6. Forwards the launch fee to the protocol treasury and emits IndexCreated.

IndexConfig

struct IndexConfig {
string name;
string symbol;
address creator; // always overwritten with msg.sender
uint256 totalSupply_;
uint16 buyFeeBps; // ≤ 1000, immutable
uint16 sellFeeBps; // ≤ 1000, immutable
address[] stocks; // 1..16, allow-listed, no duplicates
uint8 distributionMode; // reserved (0)
uint16 rfvShareBps; // 0..9000, immutable
}

Registry views

FunctionReturns
allTokens(uint256) / allTokensLength()Every index ever launched
isIndex(address)Whether an address is an IndexPad token
treasuryOf(address)The RFV treasury bound to an index
tokensByCreator(address)Indexes launched by a creator

IndexCreated event

event IndexCreated(
address indexed token,
address indexed creator,
address treasury,
string name,
string symbol,
uint256 totalSupply,
uint16 buyFeeBps,
uint16 sellFeeBps,
address[] stocks,
uint8 distributionMode,
uint16 rfvShareBps
);

This is the discovery root for the indexer — every clone is picked up from here (Ponder factory pattern), so newly launched indexes appear in the app automatically.