Create a market
To create a market, call one of the four creation functions on the MarketFactory contract. Each function corresponds to a market type; you pass a single CreateMarketParams struct. On success, the function returns the new market contract address (you can also read it from the NewMarket event).
Which function to use
createCategoricalMarket
Single-choice question (e.g. "Who will win?" β one of A, B, C).
outcomes: β₯ 2 labels. No bounds.
createMultiCategoricalMarket
Multi-choice question (e.g. "Which teams qualify?" β any subset).
outcomes: β₯ 2 labels. No bounds.
createScalarMarket
Numeric outcome in a range (e.g. "Temperature in Β°C?" between 0 and 50).
outcomes: exactly 2 (e.g. "Lower", "Higher"). Required: lowerBound, upperBound in wei (1e18).
createMultiScalarMarket
Several numeric questions (e.g. one per city).
outcomes: β₯ 2 (e.g. city names). Use questionStart, questionEnd, outcomeType to build each question; market name is built from these. No bounds.
Parameters: CreateMarketParams
CreateMarketParamsAll four functions take one argument: a struct with the following fields. Optional/conditional fields are noted.
marketName
string
Yes (except multi scalar: there it is built from questionStart/outcomeType/questionEnd).
outcomes
string[]
Yes. Categorical/multi categorical: β₯ 2. Scalar: exactly 2. Multi scalar: β₯ 2.
questionStart
string
Multi scalar only: prefix for each per-outcome question.
questionEnd
string
Multi scalar only: suffix for each per-outcome question.
outcomeType
string
Multi scalar only: placeholder in market name (e.g. "City").
parentMarket
address
Optional. Set for conditional markets; use 0x0 for root markets.
parentOutcome
uint256
Optional. For conditional markets: index of the parent outcome this market depends on.
category
string
Yes. Reality.eth category (e.g. "politics", "weather").
lang
string
Yes. Language code (e.g. "en_US").
lowerBound
uint256
Scalar only. Minimum value in wei (use e.g. parseEther("0")).
upperBound
uint256
Scalar only. Maximum value in wei (e.g. parseEther("50")). Must be > lowerBound.
minBond
uint256
Yes. Minimum bond for answering on Reality.eth (in wei).
openingTime
uint32
Yes. Unix timestamp when the question becomes answerable.
tokenNames
string[]
Yes. ERC20 symbol for each outcome (β€31 chars), one per entry in outcomes.
Getting the new market address: the contract returns it; you can also parse the NewMarket event from the transaction logs.
Struct shape (for ABI / viem):
Viem examples
We use the Viem setup: getPublicClient(chain) and getWalletClient(chain, process.env.PRIVATE_KEY). You need the MarketFactory ABI (create functions + CreateMarketParams tuple + NewMarket event). Addresses come from SEER_CONTRACTS[chain.id].
Shared: ABI and addresses
Helper: build CreateMarketParams (tuple for viem)
CreateMarketParams (tuple for viem)1. Create Categorical market (viem)
2. Create Multi Categorical market (viem)
3. Create Scalar market (viem)
Scalar bounds must be in wei (1e18 units). Use parseEther from viem to convert human-readable numbers (e.g. 0 and 50 for a 0β50 Β°C range):
4. Create Multi Scalar market (viem)
Each outcome becomes part of a Reality question: questionStart + outcomes[i] + questionEnd. The market name is questionStart + "[" + outcomeType + "]" + questionEnd.
For multi scalar markets, marketName is set to questionStart + "[" + outcomeType + "]" + questionEnd.
Last updated