Skip to main content

How the CTF Exchange Works

The Polymarket CTF Exchange implements a hybrid-decentralized exchange model that combines the efficiency of offchain order matching with the security and transparency of onchain settlement.

Hybrid-Decentralized Model

The exchange architecture separates concerns between offchain and onchain operations:

Offchain Operations

An operator provides the following services:
  • Order book management
  • Order matching and routing
  • Price discovery
  • Execution services
The operator role is permissioned and can only be granted by exchange administrators. This ensures reliable matching services while maintaining decentralization at the settlement layer.

Onchain Operations

All settlement operations happen on-chain:
  • Non-custodial: Users maintain full control of their assets
  • Atomic swaps: Trades execute atomically via signed order messages
  • Transparent: All settlements are recorded on the blockchain
  • Verifiable: Anyone can verify trade execution
Orders are represented as signed typed structured data following the EIP-712 standard, enabling secure offchain order creation with onchain verification.

Order Structure

Orders contain the following key information:
  • Maker: The address creating the order
  • Maker Asset: The asset being offered (either CTF token or collateral)
  • Taker Asset: The asset being requested
  • Maker Amount: The amount being offered
  • Taker Amount: The amount being requested
  • Fee Rate: The base fee rate for the order
  • Signature: EIP-712 signature authorizing the trade

Matching Scenarios

The CTF Exchange supports three distinct matching scenarios based on the asset types being traded.

Assets

  • A - ERC1155 outcome token
  • A' - ERC1155 outcome token, complement of A
  • C - ERC20 collateral token (e.g., USDC)
Complements have a special relationship: 1 outcome token + 1 of its complement can always be merged into 1 unit of collateral, and vice versa (A + A' = C).

Scenario 1: NORMAL

Direct swap between outcome tokens and collateral. Example:
  • UserA wants to BUY 100 token A @ $0.50 (offers 50 C)
  • UserB wants to SELL 50 token A @ $0.50 (receives 25 C)
Match Operation:
matchOrders(makerOrder, [takerOrder], 50, [25])
  1. Transfer 50 token A from UserB to CTFExchange
  2. Transfer 25 C from UserA to CTFExchange
  3. Transfer 50 token A from CTFExchange to UserA
  4. Transfer 25 C from CTFExchange to UserB

Scenario 2: MINT

When users buy complementary tokens, the exchange can mint new token sets from collateral. Example:
  • UserA wants to BUY 100 token A @ $0.50 (offers 50 C)
  • UserB wants to BUY 50 token A' @ $0.50 (offers 25 C)
Match Operation:
matchOrders(makerOrder, [takerOrder], 25, 25)
  1. Transfer 25 C from UserB to CTFExchange
  2. Transfer 25 C from UserA to CTFExchange
  3. Mint 50 token sets (= 50 token A + 50 token A')
  4. Transfer 50 token A to UserA
  5. Transfer 50 token A' to UserB
Minting allows the exchange to create liquidity by splitting collateral into complementary outcome tokens.

Scenario 3: MERGE

When users sell complementary tokens, the exchange can merge them back into collateral. Example:
  • UserA wants to SELL 50 token A @ $0.50 (receives 25 C)
  • UserB wants to SELL 100 token A' @ $0.50 (receives 50 C)
Match Operation:
matchOrders(makerOrder, [takerOrder], 50, 50)
  1. Transfer 50 A' from UserB to CTFExchange
  2. Transfer 50 A from UserA to CTFExchange
  3. Merge 50 token sets into 50 C (50 token A + 50 token A' = 50 C)
  4. Transfer 25 C to UserA
  5. Transfer 25 C to UserB
Merging reduces the total supply of outcome tokens by converting complementary pairs back into collateral.

Maker-Taker Relationship

All trades follow a maker-taker model:
  • Maker: The order(s) providing liquidity
  • Taker: The order consuming liquidity
  • Ratio: Always one-to-one or many-to-one (maker to taker)
  • Price Improvement: Captured by the taking agent
Fill amounts are always specified in terms of the maker amount, ensuring consistent pricing across all operations.

Operator Role

The operator is a privileged role responsible for:
  • Executing fillOrder() and fillOrders() functions
  • Matching orders via matchOrders()
  • Determining which orders to match and in what quantities
  • Capturing any price improvement for the taker

Access Control

  • Operators are managed by administrators
  • Only operators can execute trades
  • The exchange can be paused by administrators in emergencies
  • Trading functions are protected by the onlyOperator modifier
The operator model ensures professional market-making services while maintaining the trustless, non-custodial nature of the settlement layer.

Security Features

Reentrancy Protection

All trading functions use the nonReentrant modifier to prevent reentrancy attacks.

Pausable

Administrators can pause trading in emergency situations:
pauseTrading()   // Pause all trading
unpauseTrading() // Resume trading

Signature Validation

Orders must be signed using EIP-712 typed structured data, with support for:
  • EOA signatures (ECDSA)
  • Smart contract signatures (ERC-1271)

Nonce Management

The exchange tracks order nonces to prevent:
  • Replay attacks
  • Double-spending
  • Unauthorized order execution
Users can cancel orders by invalidating nonces before execution.

Build docs developers (and LLMs) love