PredictionLabs

Creating Markets

How to create binary and multi-outcome prediction markets on-chain.

Binary market

A YES/NO question with a deadline and a resolver.

bytes32 conditionId = factory.createMarket(
    "Will ETH hit $10k by Dec 2026?",  // question
    2,                                   // outcomeSlotCount (2 = binary)
    1767225600,                          // deadline (Unix timestamp)
    resolverAddress                      // resolver contract
);

That's it. The market is live. Anyone can trade on it immediately.

The resolver is chosen at creation time and cannot be changed. It determines how the market gets resolved - UMA, Kalshi, Polymarket, or any custom resolver.

What happens on-chain:

  1. A questionId is generated: keccak256(abi.encodePacked(question, marketCount))
  2. conditionId is derived: CTF.getConditionId(factory, questionId, 2)
  3. CTF prepares the condition (creates the YES/NO token slots)
  4. Market is stored in the factory with its metadata

Parameters:

ParamTypeRules
questionstringAny text. Becomes part of the questionId hash.
outcomeSlotCountuint2562–255. Use 2 for binary.
deadlineuint256Must be in the future. This is when the market can be resolved, not when trading stops.
resolveraddressThe resolver contract that will resolve this market. Cannot be changed after creation.

Returns: conditionId (bytes32) - the unique identifier for this market. You need this for everything: placing orders, resolving, redeeming.

Multi-outcome market

"Who wins the election?" with multiple candidates. Uses the NegRiskAdapter.

string[] memory outcomes = new string[](3);
outcomes[0] = "Trump";
outcomes[1] = "Harris";
outcomes[2] = "DeSantis";

uint256 marketId = negRiskAdapter.createMultiOutcomeMarket(
    "Who wins the 2028 election?",  // question
    outcomes,                        // outcome labels
    1762041600,                      // deadline
    resolverAddress                  // resolver contract
);

This creates 3 independent binary markets:

  • "Who wins the 2028 election? | Trump" - YES/NO
  • "Who wins the 2028 election? | Harris" - YES/NO
  • "Who wins the 2028 election? | DeSantis" - YES/NO

Each binary market has its own conditionId and trades independently on the OrderBook. All legs share the same resolver.

Get the conditionIds:

bytes32 trumpConditionId = negRiskAdapter.getOutcomeConditionId(marketId, 0);
bytes32 harrisConditionId = negRiskAdapter.getOutcomeConditionId(marketId, 1);
bytes32 desantisConditionId = negRiskAdapter.getOutcomeConditionId(marketId, 2);

Limits:

  • 2–64 outcomes
  • No duplicate labels
  • No empty labels
  • Question max 1024 bytes

Reading market data

// Get market details
(
    bytes32 questionId,
    uint64 deadline,
    uint8 outcomeSlotCount,
    bool resolved,
    address creator,
    address resolver
) = factory.markets(conditionId);

// Check if market is actively trading
bool trading = factory.isTrading(conditionId);

// Check if market can be resolved (deadline passed, not yet resolved)
bool resolvable = factory.isResolvable(conditionId);

On this page