All articles
Strategies·April 15, 2026·7 min read

Polymarket Merge/Split Arbitrage on Conditional Tokens

A practical guide to Polymarket merge split arbitrage: mint or redeem full YES+NO conditional token sets against a mispriced book for near-riskless profit.

A full set of Polymarket outcome tokens is always worth exactly one USDC. Buy one YES and one NO share for the same market, hand them back to Gnosis' Conditional Tokens Framework (CTF), and the contract returns 1 collateral token no questions asked. That invariant is the entire basis for merge/split arbitrage, and it holds regardless of what the order book thinks the market should be priced at. When the book disagrees with the invariant, the CTF contract is the counterparty that will always take the other side at par.

Most arb writeups on Polymarket stop at "buy YES + NO when they sum to less than a dollar." That's the complementary-outcome trade, and it's real, but it's only half the primitive. The splitPosition and mergePositions functions are what actually let you manufacture inventory on demand instead of hoping both legs are cheap at the same instant. Treating those two functions as first-class trading tools is where the edge lives.

The mechanic, precisely

Every Polymarket binary market is a CTF condition with two outcome slots. The framework exposes two operations against USDC collateral:

  • Split (splitPosition): lock up N USDC, receive N YES tokens and N NO tokens. You now hold a complete set for every unit deposited.
  • Merge (mergePositions): burn N YES and N NO tokens together, receive N USDC back.

Neither call touches the CLOB. There's no maker, no taker fee on the CTF side, no slippage — it's a fixed-rate conversion between collateral and a balanced set. The gas is the only friction, and on Polygon that's fractions of a cent. So you have a permanent, deterministic bridge between "1 USDC" and "1 YES + 1 NO," and a live order book quoting each leg independently. Any time those two pricings drift apart by more than fees, there's a closed loop.

Two directions:

  1. Split-and-sell (book too expensive). YES ask is 0.55, NO ask is 0.51 — no, that's the buy side. Flip it: YES bid is 0.55, NO bid is 0.51. You split 1 USDC into a set for 1.00, sell YES into the 0.55 bid and NO into the 0.51 bid, collect 1.06, keep 0.06 minus gas. You minted supply and dumped it into two rich bids.
  2. Buy-and-merge (book too cheap). YES ask is 0.46, NO ask is 0.49. Buy both for 0.95, merge the set back for 1.00, pocket 0.05. Here you're absorbing cheap supply and redeeming it at par.

The direction you use depends on which side of par the aggregate book sits, and it flips intraday. That's the part people miss — you're not waiting for one static condition, you're arbitraging the sign of (bid_yes + bid_no − 1) or (1 − ask_yes − ask_no) whenever either goes positive past your cost floor.

Why this beats plain complementary-outcome arb

Straight complementary arb needs both legs cheap on the ask side at the same moment. Merge/split decouples the legs. If only the YES side is dislocated — say a large sell order craters YES to 0.40 while NO sits fairly at 0.58 — you can buy YES at 0.40, split fresh collateral to source the NO leg you need, and merge. You're no longer hostage to both books cooperating. The split primitive is a synthetic maker on whichever leg the book won't give you cheaply.

It also means you can run inventory-neutral. Every arb cycle nets you back to flat USDC with zero directional exposure to the underlying question, because a merged set is collateral and a split set is a hedged pair by construction. That's a very different risk profile from directional prediction-market betting, and it's the reason this reads more like the market-neutral LP mechanics behind a Meteora DLMM fee-farming rebalance bot than like a punt.

A worked cycle

Say you're monitoring a market where a news-driven flush pushes both asks down:

# prices from the CLOB (best asks), 6-decimal USDC
ask_yes = 0.462
ask_no  = 0.491
set_cost = ask_yes + ask_no        # 0.953
GAS_USDC = 0.004                   # split+merge+2 fills, Polygon
FEE_BPS  = 0                       # Polymarket taker fee currently 0

edge = 1.0 - set_cost - GAS_USDC   # 0.043 per set
if edge > MIN_EDGE:                # e.g. 0.010
    size = min(depth_at(ask_yes), depth_at(ask_no))
    buy(YES, size, ask_yes)
    buy(NO,  size, ask_no)
    ctf.mergePositions(collateral, condition_id, size)
    # size * 1.0 USDC returned, minus what you paid

The size = min(depth_at(...)) line is the whole ballgame in practice. Your realized edge is set by the thinner of the two books, and both asks walk up as you eat them. Sizing off the top-of-book quote and assuming it fills at that price is the classic way to turn a 4-cent theoretical edge into a 0.5-cent realized one. Compute a depth-weighted average price for the actual clip you intend to take, and gate on that. Getting the fill-sizing model right is exactly the kind of thing worth a second pair of eyes in a strategy consultation before you wire real capital to it.

The gotchas that actually cost money

Merge only works on a matched pair. If you buy YES and NO in different sizes, mergePositions merges the min and leaves you long the remainder — now you have directional exposure you didn't want. Reconcile balances after every fill, not after the cycle.

Approvals and the operator flow. The CTF contract needs setApprovalForAll on your outcome tokens, and USDC needs an allowance for splitPosition. First-cycle latency includes those txs; pre-warm them. Polymarket also routes fills through its CLOB exchange contract, so you're signing EIP-712 orders off-chain and settling on-chain — your latency budget spans both a REST/websocket path and a Polygon inclusion delay.

Par isn't guaranteed at resolution, only at merge. Merge redeems at 1.00 any time before resolution. After resolution you use redeemPositions and only the winning side pays. Don't hold sets hoping to merge past the resolution timestamp — merge while the condition is still open.

Rounding and the 6-decimal floor. USDC is 6 decimals; CTF positions inherit that. Sub-microdollar edges disappear into rounding. Set MIN_EDGE well above dust.

Reorg and partial-fill risk. You can get one leg filled and the other rejected, leaving you naked. A merge/split bot needs the same atomic-intent discipline as any just-in-time liquidity strategy on Solana — treat the two legs plus the CTF call as one logical transaction with explicit unwind paths if any piece fails.

Building it to run unattended

The naive loop polls both books, checks the spread, and fires. The version that survives contact with real markets adds a per-market state machine tracking your open orders, filled-but-unmerged inventory, and pending CTF txs, so a crash never strands you holding an unbalanced set. Alerting on stuck inventory matters more than alerting on missed edges. If you already run a scheduled order engine — the pattern behind a Jupiter trigger and recurring-order system — the scaffolding for watching conditions and firing signed orders carries over cleanly; you're swapping the venue adapter and adding the CTF split/merge calls.

Two operational notes. Run your quote monitor and fill logic in the same process to keep the decision-to-order latency tight; a websocket feed into an in-memory book, not REST polling. And put a hard cap on per-market position size independent of book depth, because a spoofed deep bid that vanishes when you split is a fast way to end up long a set you can't unwind at par. A dashboard that surfaces open sets, unmerged inventory, and realized-versus-theoretical edge per market turns this from a black box into something you can actually trust overnight — the kind of thing a purpose-built trading dashboard is for. And because a single balance-reconciliation bug can quietly leave you directional across dozens of markets, the merge/split path is worth a proper code review and audit before it touches live funds.

If you want a second engineer to sanity-check your fill-sizing and unwind logic before it goes live, start with a strategy consultation.

Need a bot like this built?

We design, build and run trading bots on Solana, Hyperliquid and Polymarket.

Start a project
#polymarket#conditional-tokens#arbitrage#ctf#prediction-markets