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, oraddresses.MainnetRouterβ all support these calls).Gnosis (100): GnosisRouter also exposes
splitFromBase(market)(payable in xDAI),mergeToBase, andredeemToBase: 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, andredeemToDai: you work with DAI directly; the router converts to/from sDAI internally. Convenient if you prefer DAI over sDAI.
Router functions overview
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
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
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
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
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