181 lines
5.8 KiB
Markdown
181 lines
5.8 KiB
Markdown
# CTF Operations
|
|
|
|
The **Conditional Token Framework (CTF)** creates ERC1155 tokens for market outcomes. Three core operations: split, merge, redeem.
|
|
|
|
## Token Model
|
|
|
|
Every binary market has two tokens:
|
|
|
|
| Token | Redeems for | Condition |
|
|
|-------|-------------|-----------|
|
|
| **Yes** | $1.00 USDC.e | Event occurs |
|
|
| **No** | $1.00 USDC.e | Event does not occur |
|
|
|
|
Every Yes/No pair is backed by exactly $1.00 USDC.e locked in the CTF contract.
|
|
|
|
## Split
|
|
|
|
Convert USDC.e into a full set of outcome tokens.
|
|
|
|
```
|
|
$100 USDC.e → 100 Yes tokens + 100 No tokens
|
|
```
|
|
|
|
### Prerequisites
|
|
1. USDC.e balance on Polygon
|
|
2. USDC.e approval for CTF contract
|
|
3. Condition ID of the market (the condition must already be prepared on the CTF contract via `prepareCondition`)
|
|
|
|
### Function: `splitPosition`
|
|
|
|
| Parameter | Type | Value |
|
|
|-----------|------|-------|
|
|
| `collateralToken` | IERC20 | `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174` (USDC.e) |
|
|
| `parentCollectionId` | bytes32 | `0x0000...0000` (32 zero bytes) |
|
|
| `conditionId` | bytes32 | Market's condition ID |
|
|
| `partition` | uint[] | `[1, 2]` for binary (Yes=1, No=2) |
|
|
| `amount` | uint256 | Amount of USDC.e to split |
|
|
|
|
## Merge
|
|
|
|
Convert a full set of outcome tokens back to USDC.e. Inverse of split.
|
|
|
|
```
|
|
100 Yes tokens + 100 No tokens → $100 USDC.e
|
|
```
|
|
|
|
### Prerequisites
|
|
1. Equal amounts of both Yes and No tokens
|
|
2. Condition ID (the condition must already be prepared on the CTF contract via `prepareCondition`)
|
|
3. Sufficient gas for the transaction
|
|
|
|
### Function: `mergePositions`
|
|
|
|
Same parameters as split. Burns one unit of each position per unit of collateral returned.
|
|
|
|
## Redeem
|
|
|
|
Exchange winning tokens for USDC.e after market resolution.
|
|
|
|
```
|
|
Market resolves YES:
|
|
100 Yes tokens → $100 USDC.e
|
|
100 No tokens → $0
|
|
```
|
|
|
|
### Prerequisites
|
|
1. Market must be resolved
|
|
2. Hold winning tokens
|
|
3. Know the condition ID
|
|
|
|
### Function: `redeemPositions`
|
|
|
|
| Parameter | Type | Value |
|
|
|-----------|------|-------|
|
|
| `collateralToken` | IERC20 | USDC.e address |
|
|
| `parentCollectionId` | bytes32 | `0x0000...0000` |
|
|
| `conditionId` | bytes32 | Market's condition ID |
|
|
| `indexSets` | uint[] | `[1, 2]` — redeems both (only winner pays) |
|
|
|
|
Redemption burns your **entire** token balance for the condition — no amount parameter. No deadline — winning tokens are always redeemable.
|
|
|
|
### Payout Vectors
|
|
|
|
| Outcome | Payout Vector | Redemption |
|
|
|---------|---------------|------------|
|
|
| Yes wins | `[1, 0]` | Yes = $1, No = $0 |
|
|
| No wins | `[0, 1]` | Yes = $0, No = $1 |
|
|
|
|
## Contract Addresses
|
|
|
|
| Contract | Address | Purpose |
|
|
|----------|---------|---------|
|
|
| CTF | `0x4D97DCd97eC945f40cF65F87097ACe5EA0476045` | Token storage and operations |
|
|
| USDC.e (Bridged USDC) | `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174` | Collateral token |
|
|
| CTF Exchange | `0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E` | Standard market trading |
|
|
| Neg Risk CTF Exchange | `0xC5d563A36AE78145C45a50134d48A1215220f80a` | Neg risk market trading |
|
|
| Neg Risk Adapter | `0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296` | Neg risk conversions |
|
|
|
|
## Approval Matrix
|
|
|
|
Before trading or CTF operations, the funder must approve the relevant contracts:
|
|
|
|
| Operation | Contract to Approve | Token |
|
|
|-----------|-------------------|-------|
|
|
| Buy order (standard) | CTF Exchange | USDC.e |
|
|
| Sell order (standard) | CTF Exchange | Conditional tokens |
|
|
| Buy order (neg risk) | Neg Risk CTF Exchange | USDC.e |
|
|
| Sell order (neg risk) | Neg Risk CTF Exchange | Conditional tokens |
|
|
| Split | CTF | USDC.e |
|
|
| Neg risk conversion | Neg Risk Adapter | Conditional tokens |
|
|
|
|
## Standard vs Neg Risk Markets
|
|
|
|
| Feature | Standard Markets | Neg Risk Markets |
|
|
|---------|-----------------|------------------|
|
|
| CTF Contract | ConditionalTokens | ConditionalTokens |
|
|
| Exchange Contract | CTF Exchange | Neg Risk CTF Exchange |
|
|
| Multi-outcome | Independent markets | Linked via conversion |
|
|
| `negRisk` flag | `false` | `true` |
|
|
| Order option | `negRisk: false` | `negRisk: true` |
|
|
|
|
## Negative Risk
|
|
|
|
Multi-outcome events where only one outcome can win. A No token in any market can be **converted** into 1 Yes token in every other market.
|
|
|
|
### Conversion Example
|
|
|
|
Event: "Who wins?" with outcomes Trump, Harris, Other.
|
|
|
|
| Outcome | Before | After Conversion |
|
|
|---------|--------|------------------|
|
|
| Trump | — | 1 Yes |
|
|
| Harris | — | 1 Yes |
|
|
| Other | 1 No | — |
|
|
|
|
Conversion is atomic through the Neg Risk Adapter contract.
|
|
|
|
### Identifying Neg Risk Markets
|
|
|
|
```json
|
|
{
|
|
"negRisk": true // on event or market object from API
|
|
}
|
|
```
|
|
|
|
When placing orders: pass `negRisk: true` in options.
|
|
|
|
## Augmented Negative Risk
|
|
|
|
For events where new outcomes emerge after trading begins (e.g., new candidate enters race).
|
|
|
|
| Outcome Type | Description |
|
|
|--------------|-------------|
|
|
| Named outcomes | Known outcomes (e.g., "Trump", "Harris") |
|
|
| Placeholder outcomes | Reserved slots clarified later (e.g., "Person A") |
|
|
| Explicit Other | Catches any unnamed outcome |
|
|
|
|
### Identifying
|
|
|
|
```json
|
|
{
|
|
"enableNegRisk": true,
|
|
"negRiskAugmented": true
|
|
}
|
|
```
|
|
|
|
### Rules
|
|
- Only trade on **named outcomes** — ignore placeholders
|
|
- If correct outcome is not named at resolution, market resolves to "Other"
|
|
- "Other" definition changes as placeholders are clarified — avoid trading it directly
|
|
|
|
## Token ID Computation
|
|
|
|
Token IDs are computed onchain in three steps:
|
|
|
|
1. `getConditionId(oracle, questionId, outcomeSlotCount)` — oracle = UMA CTF Adapter, outcomeSlotCount = 2 for binary
|
|
2. `getCollectionId(parentCollectionId, conditionId, indexSet)` — parentCollectionId = bytes32(0), indexSet = 1 (Yes) or 2 (No)
|
|
3. `getPositionId(collateralToken, collectionId)` — combines USDC.e contract address on Polygon with collection
|
|
|
|
In practice, get token IDs from the Markets API `tokens` array. Manual computation only needed for direct contract interaction.
|