Trading
Trading outcome tokens
Outcome tokens (CTF positions) are traded on AMMs. Pools are always outcome token / main collateral for the chain.
Gnosis: Swapr (Algebra V3).
Other chains (Ethereum, Base, Optimism): Uniswap V3.
Swapr (Algebra V3) and Uniswap V3 use the same swap interface, so you can use the same router ABI for both: exactInputSingle and exactOutputSingle.
Note: The code in this guide is provided as an example (direct router calls with viem). You can also use the official Uniswap or Swapr SDK in your project and call them directly to build and send swaps; the logic for routes, amounts, and slippage is the same.
Main collateral by chain
Pools are quoted against the main collateral. Use these token addresses when building swap paths:
Gnosis (100)
sDAI
0xaf204776c7245bf4147c2612bf6e5972ee483701
Ethereum (1)
DAI
0x6B175474E89094C44Da98b954EedeAC495271d0F
Base (8453)
sUSDS
0x5875eee11cf8398102fdad704c9e96607675467a
Optimism (10)
sUSDS
0xb5b2dc7fd34c249f4be7fb1fcea07950784229e0
See also COLLATERAL_TOKENS / TOKENS_BY_CHAIN in the appβs config.
Router addresses
Gnosis
Swapr
0xffb643e73f280b97809a8b41f7232ab401a04ee1
Ethereum
Uniswap V3
0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
Base
Uniswap V3
0x2626664c2603336E57B271c5C0b26F421741e481
Optimism
Uniswap V3
0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
Use the same router ABI (Uniswap V3βcompatible) for Swapr and Uniswap V3.
Router ABI (shared)
Use the Uniswap V3 SwapRouter ABI. Relevant functions:
exactInputSingle(ExactInputSingleParams)β swap an exact amount of token-in for a minimum amount of token-out (e.g. spend X collateral, get at least Y outcome tokens).exactOutputSingle(ExactOutputSingleParams)β swap to receive an exact amount of token-out, with a maximum amount of token-in (e.g. get exactly Y outcome tokens, spend at most X collateral).
Params (same for both DEXs):
You need the fee tier of the pool (e.g. from the factory or subgraph). Common values: 500 (0.05%), 3000 (0.3%), 10000 (1%). Use sqrtPriceLimitX96 = 0 for no price limit.
Quoters (get a quote before trading)
To show the user how much they will receive or spend, call a Quoter contract before sending the swap. Quoters expose quoteExactInputSingle (exact amount in β minimum out) and quoteExactOutputSingle (exact amount out β maximum in). They are intended to be used off-chain via eth_call: the contract reverts with the result instead of returning it, so you must call and then decode the revert data.
Quoter addresses
Gnosis (100)
Swapr
0xcBaD9FDf0D2814659Eb26f600EFDeAF005Eda0F7
Ethereum (1)
Uniswap V3
0x61fFE014bA17989E743c5F6cB21bF9697530B21e (QuoterV2)
Base (8453)
Uniswap V3
0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a (QuoterV2)
Optimism (10)
Uniswap V3
0x61fFE014bA17989E743c5F6cB21bF9697530B21e (QuoterV2)
Swapr (Gnosis) uses a different interface: no fee argument; the functions return (amount, fee) so you get the pool fee from the quote. Uniswap V3 takes fee as a parameter and returns only the amount.
Swapr Quoter (Gnosis) β Algebra V3
On Gnosis, the Swapr Quoter at 0xcBaD9FDf0D2814659Eb26f600EFDeAF005Eda0F7 uses:
There is no
feeparameter; the pool fee is discovered by the quoter and returned asfee.Use
limitSqrtPrice = 0for no price limit.Use the returned
feewhen calling the SwapRouter for the actual swap.
Uniswap V3 QuoterV2 ABI (single-pool)
Uniswap QuoterV2 (used on Ethereum, Base, Optimism) takes a single struct per function and returns four values; the first is the amount. Use sqrtPriceLimitX96 = 0 for no limit.
The first return value is amountOut (or amountIn for quoteExactOutputSingle); the other three are sqrtPriceX96After, initializedTicksCrossed, and gasEstimate.
Getting the quote (viem)
Quoter functions are not view: they simulate the swap and revert with the result. So you must simulate the call and decode the revert data to get the amount (do not rely on result.data from a successful eth_call, because the contract reverts by design and some RPCs return a failed call).
Quote exact input (e.g. βI spend 10 collateral β how many outcome tokens?β):
Swapr quote (Gnosis): same idea, but use the Swapr Quoter ABI (no fee in args; returns [amountOut, fee] or [amountIn, fee]). Use the returned fee when building the swap router call:
Use the same simulate-and-decode-revert pattern as for Uniswap QuoterV2 so behaviour is consistent across RPCs.
Shared: ROUTERS and COLLATERAL
Define these once; the examples below use them as if already in scope.
Example: buy outcome tokens (collateral β outcome)
User spends collateral to receive outcome tokens. Use exactInputSingle: tokenIn = collateral, tokenOut = outcomeToken.
Example: sell outcome tokens (outcome β collateral)
User sells outcome tokens for collateral. Use exactInputSingle: tokenIn = outcomeToken, tokenOut = collateral.
Example: buy exact amount of outcome (exactOutputSingle)
When you want to receive exactly N outcome tokens and spend at most X collateral, use exactOutputSingle:
Token order and pool fee
Token order in the pool is defined by the contract (token0 < token1 by address). Your swapβs
tokenIn/tokenOutare the token addresses; the router uses the correct pool.Fee tier must match the existing pool (e.g. 3000 for 0.3%). You can read it from the pool contract or from the DEX subgraph (e.g. Swapr on Gnosis, Uniswap on other chains).
For reference, the app derives the liquidity pair (outcome token vs collateral) in getLiquidityPair and uses the same router ABI for both Swapr and Uniswap.
Last updated