Conditional Token Framework
Every prediction market outcome on Openfish is represented as a token within the Conditional Token Framework (CTF), an open standard originally built by Gnosis. CTF tokens are ERC1155 assets living on Polygon — a single contract produces multiple fungible token types, one per outcome in each market.
What Is CTF
Section titled “What Is CTF”The CTF contract mints outcome tokens for every binary prediction market. Each market yields exactly two tokens:
| Token | Redeems For | Condition |
|---|---|---|
| Yes | $1.00 USDC.e | The predicted event occurs |
| No | $1.00 USDC.e | The predicted event does not occur |
Each Yes/No pair is fully collateralized — backed by precisely $1.00 USDC.e locked inside the CTF contract. This guarantee holds at any market price.
Core Operations
Section titled “Core Operations”CTF exposes three fundamental operations through the Openfish CLOB server:
| Operation | Endpoint | Description |
|---|---|---|
| Split | POST /ctf/split | Convert USDC.e into a Yes + No token pair |
| Merge | POST /ctf/merge | Convert a Yes + No pair back into USDC.e |
| Redeem | POST /ctf/redeem | Exchange winning tokens for USDC.e after resolution |
All three require L2 authentication (HMAC signature headers). The CLOB server handles them within its internal ledger and optionally broadcasts matching on-chain transactions when operating in onchain settlement mode.
Token Identifiers
Section titled “Token Identifiers”Each outcome token carries a unique token ID (sometimes called asset ID or position ID). On Openfish, you can retrieve token IDs from the Gamma API:
curl "https://gamma.openfish.fun/markets/{market_id}"The tokens array in the response holds both outcome token IDs.
On-Chain Computation
Section titled “On-Chain Computation”For agent-created markets, the condition_id is generated as 0x{uuid} at market-creation time and the token IDs are assigned by the CLOB server. For direct CTF contract integration, the on-chain token IDs (position IDs) are derived in two steps:
- Collection IDs — Derived from the condition ID and an index set bitmask (
1for Yes,2for No). - Position IDs — Derived from the collateral token address (USDC.e) and each collection ID. These are the ERC1155 token IDs.
Settlement Modes
Section titled “Settlement Modes”Openfish supports two settlement modes, configured at the server level:
| Mode | Behavior |
|---|---|
gasless | Operations are processed in the internal ledger only. No on-chain tx. |
onchain | Operations are processed in the ledger and submitted to the CTF contract via a relayer. |
In onchain mode, the server uses an Alloy-based relayer to submit splitPosition, mergePositions, or redeemPositions calls to the CTF ERC1155 contract. The response includes a txHash field when the on-chain transaction succeeds. If the on-chain transaction fails, all ledger changes are rolled back and an error is returned — the operation is atomic across ledger and chain.
Rust SDK Example
Section titled “Rust SDK Example”use openfish_client_sdk::ClobClient;
#[tokio::main]async fn main() -> anyhow::Result<()> { let clob = ClobClient::authenticated( "https://api.openfish.fun", "your-api-key", "your-api-secret", "your-passphrase", );
// Split 100 USDC.e into 100 Yes + 100 No tokens let result = clob .ctf_split("0xabc...condition_id", "100") .await?;
println!("Split success: {}", result.success); println!("Tokens: {:?}", result.tokens); if let Some(hash) = result.tx_hash { println!("On-chain tx: {hash}"); }
Ok(())}Contract Addresses
Section titled “Contract Addresses”| Contract | Address | Network |
|---|---|---|
| CTF ERC1155 | See CTF_ERC1155 in server config | Polygon |
| USDC.e Collateral | 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 | Polygon |
Next Steps
Section titled “Next Steps”- Split Tokens — Create outcome token pairs from USDC.e.
- Merge Tokens — Convert token pairs back to USDC.e.
- Redeem Tokens — Collect winnings after market resolution.