Skip to main content
CTFExchange is a Polymarket-compatible order-matching contract that settles trades against ConditionalTokens. PredictStreet deploys it with the quadratic taker-fee formula fee = k × P × (1−P) × outcomeTokens. See Fees for the math.

Key entry points

Fee formula

Cap: feeRateBps ≤ MAX_FEE_RATE_BIPS (1000).

Events

maker (and takerOrderMaker / takerMaker) is the order’s vault address, not the signing EOA.

Security invariants

  • Signature replay impossible — every filled order’s hash stored in orderStatus[hash].isFilledOrCancelled.
  • Maker authority cryptographic — the exchange accepts only signatureType = 1 (VAULT). The signature must recover to signer, and maker must equal vaultFactory.vaultOf(signer), so the signer’s vault must already be deployed. signatureType = 0 (EOA, maker == signer) is deprecated and never validates. On-chain such orders revert with InvalidSignature(), and the API rejects them with bad_signature.
  • Admin can pause but not seize — no admin function transfers user funds.
  • Operator rotatable — removeOperator(address) disables compromised key.

MatchFailed reason codes

When batchMatchOrders catches a per-leg revert, the reason bytes are the 4-byte selector of the original custom error. Common ones: Decode the bytes with cast 4byte 0x<selector> or by computing bytes4(keccak256(<errorSig>)).
To avoid OrderExpired() settlement failures, sign orders with expiration = 0 (no on-chain expiry — the contract skips the block.timestamp >= expiration check entirely). UIs that need a hard TTL should set it well above worst-case settlement latency.

Source

0x4074c225b296E1E556c565B0C3Ddba305E63E7c4 on Blockscout (testnet). The contract is not source-verified there; request the ABI from your onboarding contact.