Split, Merge and Redeem

Use the Router (or chain-specific GnosisRouter / MainnetRouter) to split collateral into outcome tokens, merge a full set of outcome tokens back into collateral, and redeem winning outcome tokens after resolution. The market must already exist (see Create a market).

Which router and collateral:

GnosisRouter and MainnetRouter inherit from Router, so they expose the same functions (splitPosition, mergePositions, redeemPositions, getWinningOutcomes). You can call those with any collateral token on any chain.

  • Router (all networks): Pass an ERC20 collateral token and the market address; approve the collateral and call splitPosition / mergePositions / redeemPositions. Use the router address for your chain (addresses.Router, addresses.GnosisRouter, or addresses.MainnetRouter β€” all support these calls).

  • Gnosis (100): GnosisRouter also exposes splitFromBase(market) (payable in xDAI), mergeToBase, and redeemToBase: you work with xDAI directly; the router converts to/from sDAI internally (sDAI is the collateral used by the market). Convenient if you prefer xDAI over sDAI.

  • Ethereum (1): MainnetRouter also exposes splitFromDai(market, amount), mergeToDai, and redeemToDai: you work with DAI directly; the router converts to/from sDAI internally. Convenient if you prefer DAI over sDAI.


Router functions overview

Contract
Chain
Collateral
Split
Merge
Redeem

Router

All

Any ERC20 you pass

splitPosition(collateral, market, amount)

mergePositions(collateral, market, amount)

redeemPositions(collateral, market, outcomeIndexes, amounts)

GnosisRouter

Gnosis

Same as Router, or xDAI via splitFromBase / mergeToBase / redeemToBase (router converts xDAI ↔ sDAI)

splitPosition(...) or splitFromBase(market) payable

mergePositions(...) or mergeToBase(market, amount)

redeemPositions(...) or redeemToBase(market, outcomeIndexes, amounts)

MainnetRouter

Ethereum

Same as Router, or DAI via splitFromDai / mergeToDai / redeemToDai (router converts DAI ↔ sDAI)

splitPosition(...) or splitFromDai(market, amount)

mergePositions(...) or mergeToDai(market, amount)

redeemPositions(...) or redeemToDai(market, outcomeIndexes, amounts)


Split

What you do: Provide collateral (or send xDAI on Gnosis) and receive one full set of outcome tokens (one ERC20 per outcome).

Router
Parameters
What you need before calling

Router

splitPosition(collateralToken, market, amount)

Approve amount of collateralToken to the Router.

GnosisRouter

splitFromBase(market) + send value (xDAI)

Send the desired xDAI amount as value in the tx.

MainnetRouter

splitFromDai(market, amount)

Approve amount of DAI to MainnetRouter.

Parameters: collateralToken (Router only): ERC20 address. market: Market contract address. amount: amount in collateral units; you receive that many units of each outcome token.


Merge

What you do: Hold a full set of outcome tokens (same amount of each outcome), then merge them back into collateral. You receive collateral (or parent outcome tokens for conditional markets).

Router
Parameters

Router

mergePositions(collateralToken, market, amount)

GnosisRouter

mergeToBase(market, amount)

MainnetRouter

mergeToDai(market, amount)

Parameters: market, and amount (per-outcome amount you are merging). Approve the Router to spend that amount of each outcome token.


Redeem

Router
Parameters

Router

redeemPositions(collateralToken, market, outcomeIndexes, amounts)

GnosisRouter

redeemToBase(market, outcomeIndexes, amounts)

MainnetRouter

redeemToDai(market, outcomeIndexes, amounts)

What you do: After the market is resolved, redeem winning outcome tokens for collateral (or parent outcome tokens in conditional markets).

Parameters: outcomeIndexes: array of outcome indices that won (e.g. [0] or [1, 2]). amounts: amount to redeem for each (same length). Approve the Router to spend the winning outcome token(s) before calling.

How to know which outcomes won: Call the view getWinningOutcomes(conditionId) on the Router (or GnosisRouter / MainnetRouter on those chains) with the market's conditionId; the returned array has true for each winning outcome index.

ABI and example (viem):


Conditional markets

For conditional (child) markets, the β€œcollateral” for that market is a parent outcome token (ERC20 from a parent market), not the chain’s base collateral.

  • Split: user holds parent outcome tokens; splitting mints child outcome tokens (one set per amount).

  • Merge: user holds a full set of child outcome tokens (equal amount of each outcome); merging returns parent outcome tokens.

  • Redeem: after the child market is resolved, user redeems winning child outcome tokens for parent outcome tokens (not base collateral until the parent is also resolved and redeemed).

Use the same Router functions with the child market; pass the parent's wrapped outcome token as the collateral token for split/merge/redeem (see Conditional market).


Viem examples

We use the Viem setup: getPublicClient(chain) and getWalletClient(chain, process.env.PRIVATE_KEY). Addresses come from SEER_CONTRACTS[chain.id] (Router on Optimism/Base, GnosisRouter on Gnosis, MainnetRouter on Ethereum). The user must have approved the collateral (or sent native xDAI for Gnosis) and the market must exist.

Shared: addresses


1. splitPosition / mergePositions / redeemPositions (any router)

The functions splitPosition, mergePositions, and redeemPositions exist on the base Router and are also available on GnosisRouter and MainnetRouter (they extend Router). Use the router address for your chain (addresses.Router, addresses.GnosisRouter, or addresses.MainnetRouter) and pass the collateral token address (e.g. sDAI or sUSDS, or the parent outcome token for conditional markets) and the market address.

Split:

Merge:

Redeem (after market is resolved):


2. GnosisRouter (Gnosis Chain)

GnosisRouter implements helpers so you can work with xDAI directly instead of sDAI: you send native xDAI with splitFromBase, and mergeToBase / redeemToBase return xDAI. The router converts to/from sDAI internally (sDAI is the collateral used by the market). Use addresses.GnosisRouter (chain 100) when you prefer xDAI.

Split (send xDAI; router converts to sDAI internally):

Merge:

Redeem:


3. MainnetRouter (Ethereum mainnet)

MainnetRouter implements helpers so you can work with DAI directly instead of sDAI: you approve DAI for splitFromDai, and mergeToDai / redeemToDai return DAI. The router converts to/from sDAI internally. Use addresses.MainnetRouter (chain 1) when you prefer DAI.

Split (approve DAI; router converts to sDAI internally):

Merge / Redeem: Same pattern as GnosisRouter but with mergeToDai and redeemToDai (router converts sDAI back to DAI). You must approve the MainnetRouter to spend outcome tokens before calling merge or redeem: for merge, approve amount of each outcome token (get addresses via market.wrappedOutcome(i)); for redeem, approve each winning outcome token for the corresponding amount in amounts. Use the same ERC20 approve(spender, amount) pattern as in the GnosisRouter examples above.


Simulate before sending

To avoid reverts (e.g. insufficient allowance or balance), simulate first:

For GnosisRouter splitFromBase, include value in simulateContract if your client supports it for payable calls.


Summary

Action
Router (generic)
GnosisRouter
MainnetRouter

Split

Approve collateral β†’ splitPosition(collateral, market, amount)

Send xDAI β†’ splitFromBase(market) (router β†’ sDAI)

Approve DAI β†’ splitFromDai(market, amount) (router β†’ sDAI)

Merge

Hold one set of outcomes β†’ mergePositions(collateral, market, amount)

mergeToBase(market, amount) β†’ receive xDAI (router redeems sDAI)

mergeToDai(market, amount) β†’ receive DAI (router redeems sDAI)

Redeem

After resolve β†’ redeemPositions(collateral, market, outcomeIndexes, amounts)

redeemToBase(...) β†’ xDAI

redeemToDai(...) β†’ DAI

Last updated