Skip to main content
合併(Merging)是將完整的條件代幣集合轉換回 USDC 的過程。這是拆分的反向操作。

什麼是合併?

合併允許持有完整代幣集合的用戶將代幣轉換回原始抵押品(USDC)。在二元市場中:
1 Yes 代幣 + 1 No 代幣 = 1 USDC
價值回收:合併允許你無損失地退出市場,前提是你持有完整的代幣集合。

為什麼要合併?

1. 退出頭寸

如果你改變主意不想參與市場:
持有: 100 Yes + 100 No
合併: → 100 USDC
結果: 完全退出,零損失

2. 套利

當市場價格和 < 1 时:
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. 做市结束

做市商完成做市后可以合并剩余代币:
初始: 拆分 1000 USDC → 1000 Yes + 1000 No
卖出: 800 Yes, 800 No
剩余: 200 Yes + 200 No
合并: → 200 USDC
回收: 200 USDC 的资本

合并条件

要成功合并,你必须:
  1. 持有完整集合:对于二元市场,需要相同数量的 Yes 和 No 代币
  2. 市场未结算:合并只能在市场结算前进行
  3. 相同条件:所有代币必须来自同一个条件 ID
注意:你只能合併你持有的最小數量。例如,如果你有 100 Yes 和 80 No,只能合併 80 USDC,剩餘 20 Yes。

合併流程

方法 1:通過 Polymarket 界面

  1. 訪問你持有代幣的市場
  2. 查找”Merge Position”或類似選項
  3. 輸入要合併的數量
  4. 確認交易

方法 2:直接調用智能合約

Python 示例

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 示例

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();

檢查可合併數量

在合併前,檢查你可以合併多少:
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)

批量合併

如果你在多個市場都有完整代幣集合,可以批量合併:
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 餘額增加:
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")

套利策略示例

完整的套利策略實現:
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秒检查一次

注意事项

重要提示
  1. 餘額不足:確保你有足夠的 Yes 和 No 代幣
  2. 條件 ID 正確:使用錯誤的條件 ID 會導致交易失敗
  3. 市場已結算:結算後的市場不能合併,只能贖回
  4. Gas 費用:需要一些 MATIC 支付 Gas
  5. 滑點:如果要先買入再合併,注意價格變動

常見問題

Q: 可以部分合併嗎?

A: 可以!你可以合併任意數量,只要不超過你持有的最小數量。

Q: 合併後代幣還在嗎?

A: 不在了。合併會銷毀代幣並返還 USDC。

Q: 市場結算後還能合併嗎?

A: 不能。市場結算後,只能贖回獲勝代幣,不能合併。

Q: 合併有時間限制嗎?

A: 沒有。只要市場未結算,隨時可以合併。

Q: 合併會虧損嗎?

A: 不會。合併總是 1:1 換回 USDC,沒有任何費用或滑點。

下一步