還沒有帳號?點擊這裡註冊 Polymarket 並完成入金,才能用錢包私鑰為訂單籤名、實際成交。
法律合規提醒:在使用 Polymarket 服務或 API 前,請確認您所在地區的法律規定。Polymarket 目前不支援比利時、法國、新加坡、泰國、中國大陸等地區,政策可能隨時變化。
主要合約地址
Polygon 主網
這是 Polymarket 主要運行的網絡:| 合約 | 地址 | 說明 |
|---|---|---|
| ConditionalTokens | 0x4D97DCd97eC945f40cF65F87097ACe5EA0476045 | 核心 CTF 合約 |
| CTF Exchange | 0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E | 交換合約 |
| USDC | 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 | 主要抵押品 |
| CLOB | 鏈下系統 | 中央限價訂單簿 |
網絡信息:
- 網絡名稱:Polygon (Matic)
- Chain ID:137
- RPC URL:https://polygon-rpc.com
- 區塊瀏覽器:https://polygonscan.com
以太坊主網(原始部署)
CTF 最初在以太坊主網部署,但 Polymarket 現在主要使用 Polygon:| 合約 | 地址 |
|---|---|
| ConditionalTokens | 0xC59b0e4De5F1248C1140964E0fF287B192407E0C |
| USDC | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
合約 ABI
ConditionalTokens 主要函數
[
{
"name": "prepareCondition",
"type": "function",
"inputs": [
{"name": "oracle", "type": "address"},
{"name": "questionId", "type": "bytes32"},
{"name": "outcomeSlotCount", "type": "uint256"}
]
},
{
"name": "splitPosition",
"type": "function",
"inputs": [
{"name": "collateralToken", "type": "address"},
{"name": "parentCollectionId", "type": "bytes32"},
{"name": "conditionId", "type": "bytes32"},
{"name": "partition", "type": "uint256[]"},
{"name": "amount", "type": "uint256"}
]
},
{
"name": "mergePositions",
"type": "function",
"inputs": [
{"name": "collateralToken", "type": "address"},
{"name": "parentCollectionId", "type": "bytes32"},
{"name": "conditionId", "type": "bytes32"},
{"name": "partition", "type": "uint256[]"},
{"name": "amount", "type": "uint256"}
]
},
{
"name": "redeemPositions",
"type": "function",
"inputs": [
{"name": "collateralToken", "type": "address"},
{"name": "parentCollectionId", "type": "bytes32"},
{"name": "conditionId", "type": "bytes32"},
{"name": "indexSets", "type": "uint256[]"}
]
},
{
"name": "balanceOf",
"type": "function",
"inputs": [
{"name": "owner", "type": "address"},
{"name": "positionId", "type": "uint256"}
],
"outputs": [
{"name": "balance", "type": "uint256"}
]
}
]
完整 ABI 文件
完整的 ABI 可以從以下來源獲取:-
Polygonscan:
https://polygonscan.com/address/0x4D97DCd97eC945f40cF65F87097ACe5EA0476045#code -
Gnosis CTF GitHub:
https://github.com/gnosis/conditional-tokens-contracts -
NPM 包:
npm install @gnosis.pm/conditional-tokens-contracts
技術規格
代幣標準
- 標準:ERC-1155(多代幣標準)
- 小數位:繼承自抵押品(USDC = 6位)
- 位置 ID:256位哈希
ID 計算
條件 ID
function getConditionId(
address oracle,
bytes32 questionId,
uint256 outcomeSlotCount
) public pure returns (bytes32) {
return keccak256(
abi.encodePacked(
oracle,
questionId,
outcomeSlotCount
)
);
}
集合 ID
function getCollectionId(
bytes32 parentCollectionId,
bytes32 conditionId,
uint256 indexSet
) public pure returns (bytes32) {
return keccak256(
abi.encodePacked(
parentCollectionId,
conditionId,
indexSet
)
);
}
位置 ID
function getPositionId(
address collateralToken,
bytes32 collectionId
) public pure returns (uint256) {
return uint256(
keccak256(
abi.encodePacked(
collateralToken,
collectionId
)
)
);
}
Python 工具函數
完整的 Python 實現:from web3 import Web3
from eth_abi import encode
def get_condition_id(oracle: str, question_id: bytes, outcome_count: int) -> str:
"""計算條件 ID"""
return Web3.keccak(
bytes.fromhex(oracle[2:].zfill(64)) +
question_id +
outcome_count.to_bytes(32, 'big')
).hex()
def get_collection_id(
parent_collection_id: str,
condition_id: str,
index_set: int
) -> str:
"""計算集合 ID"""
return Web3.keccak(
bytes.fromhex(parent_collection_id[2:]) +
bytes.fromhex(condition_id[2:]) +
index_set.to_bytes(32, 'big')
).hex()
def get_position_id(collateral_token: str, collection_id: str) -> str:
"""計算位置 ID"""
return Web3.keccak(
bytes.fromhex(collateral_token[2:].lower().zfill(64)) +
bytes.fromhex(collection_id[2:])
).hex()
def get_position_ids_for_market(
collateral_token: str,
condition_id: str
) -> tuple:
"""獲取市場的 Yes 和 No 位置 ID"""
parent_collection_id = '0x' + '0' * 64
# Yes (index_set = 1)
yes_collection_id = get_collection_id(
parent_collection_id,
condition_id,
1
)
yes_position_id = get_position_id(collateral_token, yes_collection_id)
# No (index_set = 2)
no_collection_id = get_collection_id(
parent_collection_id,
condition_id,
2
)
no_position_id = get_position_id(collateral_token, no_collection_id)
return yes_position_id, no_position_id
# 使用示例
usdc = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174'
condition_id = '0xabc123...'
yes_id, no_id = get_position_ids_for_market(usdc, condition_id)
print(f"Yes Position ID: {yes_id}")
print(f"No Position ID: {no_id}")
TypeScript 工具函數
import { ethers } from 'ethers';
export function getConditionId(
oracle: string,
questionId: string,
outcomeCount: number
): string {
return ethers.utils.keccak256(
ethers.utils.solidityPack(
['address', 'bytes32', 'uint256'],
[oracle, questionId, outcomeCount]
)
);
}
export function getCollectionId(
parentCollectionId: string,
conditionId: string,
indexSet: number
): string {
return ethers.utils.keccak256(
ethers.utils.solidityPack(
['bytes32', 'bytes32', 'uint256'],
[parentCollectionId, conditionId, indexSet]
)
);
}
export function getPositionId(
collateralToken: string,
collectionId: string
): string {
return ethers.BigNumber.from(
ethers.utils.keccak256(
ethers.utils.solidityPack(
['address', 'bytes32'],
[collateralToken, collectionId]
)
)
).toString();
}
export function getPositionIdsForMarket(
collateralToken: string,
conditionId: string
): { yes: string; no: string } {
const parentCollectionId = '0x' + '0'.repeat(64);
// Yes (index_set = 1)
const yesCollectionId = getCollectionId(
parentCollectionId,
conditionId,
1
);
const yesPositionId = getPositionId(collateralToken, yesCollectionId);
// No (index_set = 2)
const noCollectionId = getCollectionId(
parentCollectionId,
conditionId,
2
);
const noPositionId = getPositionId(collateralToken, noCollectionId);
return { yes: yesPositionId, no: noPositionId };
}
// 使用示例
const usdc = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174';
const conditionId = '0xabc123...';
const { yes, no } = getPositionIdsForMarket(usdc, conditionId);
console.log('Yes Position ID:', yes);
console.log('No Position ID:', no);
網絡配置
添加 Polygon 到 MetaMask
// 網絡參數
const polygonParams = {
chainId: '0x89', // 137 in hex
chainName: 'Polygon Mainnet',
nativeCurrency: {
name: 'MATIC',
symbol: 'MATIC',
decimals: 18
},
rpcUrls: ['https://polygon-rpc.com'],
blockExplorerUrls: ['https://polygonscan.com']
};
// 添加網絡
await window.ethereum.request({
method: 'wallet_addEthereumChain',
params: [polygonParams]
});
Python Web3 配置
from web3 import Web3
# Polygon 主網
w3 = Web3(Web3.HTTPProvider('https://polygon-rpc.com'))
# 驗證連接
if w3.is_connected():
print(f"✓ 已連接到 Polygon")
print(f"當前區塊: {w3.eth.block_number}")
print(f"Chain ID: {w3.eth.chain_id}")
else:
print("✗ 連接失敗")
Gas 優化建議
批量操作
# ✓ 好:批量操作
positions = [(condition_id_1, amount_1), (condition_id_2, amount_2)]
batch_redeem(positions) # 一次交易
# ✗ 差:單獨操作
redeem(condition_id_1, amount_1) # Gas: ~110k
redeem(condition_id_2, amount_2) # Gas: ~110k
# 總 Gas: ~220k
# 批量可能只需要 ~180k Gas
Gas 估算
# 估算 Gas
gas_estimate = ctf_contract.functions.redeemPositions(
usdc_address,
parent_collection_id,
condition_id,
[1]
).estimate_gas({'from': your_address})
print(f"估算 Gas: {gas_estimate}")
# 添加 20% 緩衝
gas_limit = int(gas_estimate * 1.2)
安全審計
CTF 合約已通過多次專業審計:審計報告
開原始碼
- GitHub:https://github.com/gnosis/conditional-tokens-contracts
- 文檔:https://docs.gnosis.io/conditionaltokens/
- 許可證:LGPL-3.0
相關資源
Polygonscan
查看合約詳情
GitHub 倉庫
訪問原始碼
Gnosis 文檔
技術文檔
CTF 白皮書
閱讀白皮書
下一步
拆分 USDC
開始使用 CTF
CTF 概覽
理解 CTF 原理
CLOB API
學習 CLOB 交易
第一筆訂單
下第一筆訂單