什麼是合併?
合併允許持有完整代幣集合的用戶將代幣轉換回原始抵押品(USDC)。在二元市場中:Copy
1 Yes 代幣 + 1 No 代幣 = 1 USDC
價值回收:合併允許你無損失地退出市場,前提是你持有完整的代幣集合。
為什麼要合併?
1. 退出頭寸
如果你改變主意不想參與市場:Copy
持有: 100 Yes + 100 No
合併: → 100 USDC
結果: 完全退出,零損失
2. 套利
當市場價格和 < 1 时:Copy
Yes 价格: 0.48 USDC
No 价格: 0.50 USDC
总和: 0.98 USDC (套利机会!)
操作:
1. 买入 Yes @0.48 → 成本 480 USDC (买1000个)
2. 买入 No @0.50 → 成本 500 USDC (买1000个)
3. 总成本: 980 USDC
4. 合并: 1000 Yes + 1000 No → 1000 USDC
5. 利润: 1000 - 980 = 20 USDC
3. 做市结束
做市商完成做市后可以合并剩余代币:Copy
初始: 拆分 1000 USDC → 1000 Yes + 1000 No
卖出: 800 Yes, 800 No
剩余: 200 Yes + 200 No
合并: → 200 USDC
回收: 200 USDC 的资本
合并条件
要成功合并,你必须:- 持有完整集合:对于二元市场,需要相同数量的 Yes 和 No 代币
- 市场未结算:合并只能在市场结算前进行
- 相同条件:所有代币必须来自同一个条件 ID
注意:你只能合併你持有的最小數量。例如,如果你有 100 Yes 和 80 No,只能合併 80 USDC,剩餘 20 Yes。
合併流程
方法 1:通過 Polymarket 界面
- 訪問你持有代幣的市場
- 查找”Merge Position”或類似選項
- 輸入要合併的數量
- 確認交易
方法 2:直接調用智能合約
Python 示例
Copy
from web3 import Web3
# 連接到 Polygon
w3 = Web3(Web3.HTTPProvider('https://polygon-rpc.com'))
# CTF 合約
ctf_address = '0x4D97DCd97eC945f40cF65F87097ACe5EA0476045'
ctf_abi = [...] # CTF ABI
ctf_contract = w3.eth.contract(address=ctf_address, abi=ctf_abi)
# USDC 地址
usdc_address = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174'
# 市場信息
condition_id = '0x...' # 市場的條件 ID
partition = [1, 2] # [Yes, No]
amount = 100 * 10**6 # 100 USDC 價值的代幣 (6位小數)
# 合併位置
merge_tx = ctf_contract.functions.mergePositions(
usdc_address, # 抵押品代幣 (USDC)
'0x' + '0' * 64, # 父集合 ID (0 表示頂層)
condition_id, # 條件 ID
partition, # [Yes, No]
amount # 要合併的數量
).build_transaction({
'from': your_address,
'nonce': w3.eth.get_transaction_count(your_address),
'gas': 200000,
'gasPrice': w3.eth.gas_price
})
# 籤署並發送交易
signed_tx = w3.eth.account.sign_transaction(merge_tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"合併成功! 交易哈希: {tx_hash.hex()}")
print(f"Gas 使用: {receipt['gasUsed']}")
TypeScript 示例
Copy
import { ethers } from 'ethers';
// 連接到 Polygon
const provider = new ethers.providers.JsonRpcProvider('https://polygon-rpc.com');
const wallet = new ethers.Wallet(privateKey, provider);
// CTF 合約
const ctfAddress = '0x4D97DCd97eC945f40cF65F87097ACe5EA0476045';
const ctfAbi = [...]; // CTF ABI
const ctfContract = new ethers.Contract(ctfAddress, ctfAbi, wallet);
// USDC 地址
const usdcAddress = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174';
async function mergePositions() {
const conditionId = '0x...'; // 市場的條件 ID
const parentCollectionId = '0x' + '0'.repeat(64);
const partition = [1, 2]; // [Yes, No]
const amount = ethers.utils.parseUnits('100', 6); // 100 USDC
try {
// 合併位置
const mergeTx = await ctfContract.mergePositions(
usdcAddress,
parentCollectionId,
conditionId,
partition,
amount
);
console.log('交易已發送:', mergeTx.hash);
const receipt = await mergeTx.wait();
console.log('合併成功!');
console.log('Gas 使用:', receipt.gasUsed.toString());
} catch (error) {
console.error('合併失敗:', error);
}
}
mergePositions();
檢查可合併數量
在合併前,檢查你可以合併多少:Copy
from web3 import Web3
def get_mergeable_amount(address, yes_position_id, no_position_id):
"""
計算可以合併的最大數量
"""
# 查詢 Yes 代幣餘額
balance_yes = ctf_contract.functions.balanceOf(
address,
int(yes_position_id, 16)
).call()
# 查詢 No 代幣餘額
balance_no = ctf_contract.functions.balanceOf(
address,
int(no_position_id, 16)
).call()
# 可合併數量是兩者中的最小值
mergeable = min(balance_yes, balance_no)
print(f"Yes 餘額: {balance_yes / 10**6} USDC")
print(f"No 餘額: {balance_no / 10**6} USDC")
print(f"可合併: {mergeable / 10**6} USDC")
return mergeable
# 使用示例
yes_id = '0x...' # Yes 代幣的位置 ID
no_id = '0x...' # No 代幣的位置 ID
mergeable = get_mergeable_amount(your_address, yes_id, no_id)
批量合併
如果你在多個市場都有完整代幣集合,可以批量合併:Copy
def batch_merge(markets_info):
"""
批量合併多個市場的代幣
Args:
markets_info: 列表,每個元素包含 {condition_id, amount}
"""
for market in markets_info:
condition_id = market['condition_id']
amount = market['amount']
merge_tx = ctf_contract.functions.mergePositions(
usdc_address,
'0x' + '0' * 64,
condition_id,
[1, 2],
amount
).build_transaction({
'from': your_address,
'nonce': w3.eth.get_transaction_count(your_address),
})
signed_tx = w3.eth.account.sign_transaction(merge_tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
print(f"市場 {condition_id[:8]}... 合併交易: {tx_hash.hex()}")
# 等待確認
w3.eth.wait_for_transaction_receipt(tx_hash)
print(f" ✓ 已確認")
# 使用示例
markets = [
{'condition_id': '0xabc...', 'amount': 50 * 10**6},
{'condition_id': '0xdef...', 'amount': 100 * 10**6},
{'condition_id': '0x123...', 'amount': 75 * 10**6},
]
batch_merge(markets)
Gas 成本
合併操作的典型 Gas 成本(Polygon):| 操作 | Gas 使用量 | 成本 @ 100 Gwei |
|---|---|---|
| 單次合併 | ~100,000 | $0.010 |
| 批量合併 (3個) | ~280,000 | $0.028 |
合併操作比拆分稍微便宜一些,因為它不需要額外的授權步驟。
合併後驗證
合併後,驗證你的 USDC 餘額增加:Copy
from web3 import Web3
# USDC 合約
usdc_contract = w3.eth.contract(
address=usdc_address,
abi=usdc_abi
)
# 檢查 USDC 餘額
balance_before = usdc_contract.functions.balanceOf(your_address).call()
print(f"合併前 USDC: {balance_before / 10**6}")
# 執行合併...
balance_after = usdc_contract.functions.balanceOf(your_address).call()
print(f"合併後 USDC: {balance_after / 10**6}")
increased = (balance_after - balance_before) / 10**6
print(f"增加: {increased} USDC")
套利策略示例
完整的套利策略實現:Copy
def arbitrage_opportunity(market_id):
"""
檢測並執行套利機會
"""
# 1. 獲取當前價格
book_yes = client.get_order_book(yes_token_id)
book_no = client.get_order_book(no_token_id)
best_ask_yes = float(book_yes['asks'][0]['price'])
best_ask_no = float(book_no['asks'][0]['price'])
total_price = best_ask_yes + best_ask_no
# 2. 檢查套利機會
if total_price < 0.99: # 留 1% 利润空间
print(f"发现套利机会! 总价: {total_price}")
# 3. 买入两边
size = 100 # 买入 100 个
# 买入 Yes
buy_yes = client.create_order(OrderArgs(
price=best_ask_yes,
size=size,
side=BUY,
token_id=yes_token_id
))
client.post_order(buy_yes, OrderType.GTC)
# 买入 No
buy_no = client.create_order(OrderArgs(
price=best_ask_no,
size=size,
side=BUY,
token_id=no_token_id
))
client.post_order(buy_no, OrderType.GTC)
# 4. 等待成交后合并
time.sleep(5) # 等待成交
merge_amount = size * 10**6
merge_positions(condition_id, merge_amount)
profit = size * (1 - total_price)
print(f"套利利润: {profit} USDC")
else:
print(f"无套利机会,总价: {total_price}")
# 监控并执行
while True:
arbitrage_opportunity(market_id)
time.sleep(10) # 每10秒检查一次
注意事项
重要提示:
- 餘額不足:確保你有足夠的 Yes 和 No 代幣
- 條件 ID 正確:使用錯誤的條件 ID 會導致交易失敗
- 市場已結算:結算後的市場不能合併,只能贖回
- Gas 費用:需要一些 MATIC 支付 Gas
- 滑點:如果要先買入再合併,注意價格變動