Conditional market

A conditional market is a market that depends on a specific outcome of an existing (parent) market. The child market’s positions are backed by the parent’s outcome token, not by the chain’s base collateral. For example: β€œWill Russia withdraw all troops from Ukrainian territory by end of 2025?” conditional on the parent β€œWill the war in Ukraine end in 2024?” resolving to Yes (outcome index 0).

You create conditional markets with the same MarketFactory functions as root markets (e.g. createCategoricalMarket), but you set parentMarket and parentOutcome in CreateMarketParams. Split, merge and redeem use the same Router (or chain-specific router) with the parent’s outcome token as the collateral token for the child market. Redeeming a resolved conditional market returns parent outcome tokens; to get base collateral in one go you can use ConditionalRouter.redeemConditionalToCollateral when the parent is a root market.


Creating a conditional market

Use any of the four market-creation functions on the MarketFactory and pass a parent market address and parent outcome index in the params. The child market is tied to β€œparent resolves to this outcome.”

Parameter
Type
Description

parentMarket

address

Parent market contract address. Use address(0) for a root (non-conditional) market.

parentOutcome

uint256

Index of the parent outcome this market is conditional on (e.g. 0 = Yes, 1 = No in a binary market).

Split, merge and redeem

The same Router (or GnosisRouter / MainnetRouter) is used. The important difference is the collateral token:

  • Root market: collateral token = base collateral (e.g. sDAI or sUSDS, or the yield-bearing ERC20 you use on that chain).

  • Conditional market: collateral token = parent’s wrapped outcome token (the ERC20 for the parent outcome at index parentOutcome).

So for a conditional market you do not use splitFromBase (Gnosis) or splitFromDai (Mainnet); you use splitPosition(collateralToken, market, amount) where collateralToken is the parent outcome ERC20.

Split

You must hold enough parent outcome tokens (from splitting or trading the parent market). Then:

  1. Approve the parent’s wrapped outcome token (for the outcome index the child is conditional on) to the Router.

  2. Call router.splitPosition(parentWrappedOutcomeToken, conditionalMarket, amount).

You receive a full set of child outcome tokens (one ERC20 per outcome).

Merge

Hold a full set of child outcome tokens (equal amount of each outcome; e.g. 50 of outcome A and 50 of outcome B). Call:

router.mergePositions(parentWrappedOutcomeToken, conditionalMarket, amount).

You receive parent outcome tokens back.

Redeem (after child market is resolved)

Call router.redeemPositions(parentWrappedOutcomeToken, conditionalMarket, outcomeIndexes, amounts) with the winning child outcome index(es) and amounts. You receive parent outcome tokens (not base collateral). To get base collateral you must either:

  • Redeem the parent market separately (if the parent is resolved), or

  • Use ConditionalRouter.redeemConditionalToCollateral (see below), which redeems child winning positions and then redeems the resulting parent outcome to collateral in one tx. The parent must be a root market (not conditional).


ConditionalRouter: redeem to collateral in one call

ConditionalRouter extends Router and adds:

  • outcomeIndexes / amounts: winning child outcome(s) to redeem.

  • parentOutcomeIndexes: which parent outcome(s) to redeem when converting the received parent tokens to collateral (e.g. [0] if the parent resolved to outcome 0).

The parent market must be a root market (not conditional). The function redeems the child positions and then the parent outcome tokens, and sends collateral to the user.


Nested conditional markets

The framework supports multiple levels: a market can be conditional on another conditional market. Interact with each level the same way (collateral token for a child is always the parent’s wrapped outcome token).

If the parent resolves to an outcome different from the one the child is conditional on, the child market (and any deeper nesting) becomes obsolete: no one can redeem that branch for value.


Viem examples

We use the Viem setup: getPublicClient(chain) and getWalletClient(chain, process.env.PRIVATE_KEY). Addresses come from SEER_CONTRACTS[chain.id]. You also need the MarketFactory and Router (or GnosisRouter/MainnetRouter) ABIs, and a parent market already created. The parent can be root or conditional.

1. Create a conditional categorical market

Use the same createMarketParams helper and MarketFactory ABI as in Create a market, and set parentMarket and parentOutcome:

2. Get parent wrapped outcome token (for split/merge/redeem)

The β€œcollateral” token for the conditional market in Router calls is the parent’s wrapped outcome ERC20. You can read it from the child market (if the contract exposes it) or from the parent:

3. Split on a conditional market

Approve the parent outcome token to the Router, then call splitPosition with that token and the conditional market. Use addresses.Router (Optimism/Base), addresses.GnosisRouter (Gnosis), or addresses.MainnetRouter (Ethereum) as appropriate for your chain.

4. Merge on a conditional market

You need a full set of child outcome tokens (equal amount of each outcome). Same Router and β€œcollateral” token (parent wrapped outcome). Approve the router to spend amount of each child outcome token before calling merge:

5. Redeem (child resolved) β†’ parent outcome tokens

After the child market is resolved, redeem winning child outcome(s). You receive parent outcome tokens. Approve the router to spend each winning child outcome token for the corresponding amount before calling redeem. Use a Router ABI that includes redeemPositions(collateralToken, market, outcomeIndexes, amounts) (see Split, merge and redeem):

6. Redeem to base collateral in one tx (ConditionalRouter)

If the parent is a root market and is already resolved, you can use ConditionalRouter to redeem child winning positions and get collateral in one call. Use addresses.ConditionalRouter. Approve the ConditionalRouter to spend each winning child outcome token for the corresponding amount before calling.


Summary

Step
What to use

Create

MarketFactory (e.g. createCategoricalMarket) with parentMarket and parentOutcome in params.

Collateral token for Router

Parent’s wrapped outcome token (read via parent’s wrappedOutcome(parentOutcome) or child’s parent info).

Split

Hold parent outcome tokens β†’ approve parent wrapped token β†’ router.splitPosition(parentWrappedToken, conditionalMarket, amount).

Merge

Hold full set of child outcome tokens (equal amount of each) β†’ router.mergePositions(parentWrappedToken, conditionalMarket, amount) β†’ receive parent outcome tokens.

Redeem

After child resolved β†’ router.redeemPositions(...) β†’ receive parent outcome tokens; or use ConditionalRouter.redeemConditionalToCollateral to get base collateral in one tx (parent must be root and resolved).

Last updated