Polymarket V2 — what changed
The full delta from V1 to V2, with the implications for every layer of the Polytraders stack. V1 was removed from production on Apr 28, 2026; this page is now historical reference for migration audits.
The seven big changes
| Area | V1 | V2 |
|---|---|---|
| SDK | @polymarket/clob-client / py-clob-client | @polymarket/clob-client-v2 / py-clob-client-v2 |
| Collateral | USDC.e (bridged USDC) | pUSD (USDC-backed standard ERC-20) |
| Order fields | nonce, feeRateBps, taker | timestamp (ms) + metadata (bytes32) + builder (bytes32) |
| Fees | Embedded in the signed order | Operator-set at match time, not on the signed order |
| EIP-712 Exchange domain version | "1" | "2" (ClobAuth stays at "1") |
| Settlement contract | CTFExchange on Polygon | CTFExchangeV2 on Polygon — matchOrders() |
| Builder attribution | HMAC headers POLY_BUILDER_* + builder-signing-sdk | Native builderCode field on order; maker max 50 bps, taker max 100 bps, 1 bp granularity |
Why this matters for every bot
- Risk bots that pre-compute fees from a signed order's
feeRateBpsare wrong on V2 — fees come from the operator at match time. Compute them post-fill from theplatform_feeformula. - Security bots must allow-list V2 contracts only. The V1
CTFExchangeaddress must be in the deny-list now (handled by ContractAddressGuard). - Execution bots must use the new
timestamp/metadata/builderfield set on orders. Hand-rolled signers from V1 will sign garbage on V2. - Governance bots attributing builder revenue must read the on-order
builderCode, not the V1 HMAC headers. - Intelligence bots reading historical fills must understand the cutover: fills before Apr 28, 2026 are V1; after are V2. The Data API exposes a
versionfield per fill.
EIP-712 migration trap
The Exchange domain version moved "1" → "2", but the ClobAuth domain stayed at "1". Conflating them produces silent rejects with no error code from the order book. The SDK helpers buildOrderTypedData and buildClobAuthTypedData get this right; do not hand-roll.
Builder fee math (V2)
builder_fee = notional × builder_fee_rate_bps / 10000
caps:
taker_fee_rate_bps ≤ 100 (1.00%)
maker_fee_rate_bps ≤ 50 (0.50%)
granularity:
1 bp (no fractional bps)
note:
The maker and taker sides of one trade can carry different builder codes
(different integrators on each side).
Platform fee (V2, unchanged from late V1)
platform_fee = C × feeRate × p × (1 − p)
// peaks at p = 0.5
current operator policy (Apr 2026):
taker-only (no maker fee)
crypto markets: up to 1.80%
sports markets: 0.75%
geopolitical / global: 0%
Maker rebates
20–25% of fees collected, paid in pUSD, calculated per market. April 2026 pool: $5M for sports + esports. Specific allocation is at the operator's discretion and can change month-to-month — bots should never hard-code rebate amounts.
Source documents
- docs.polymarket.com/v2-migration
- docs.polymarket.com/builders/fees
- docs.polymarket.com/trading/fees
- docs.polymarket.com/market-makers/liquidity-rewards
- docs.polymarket.com/concepts/resolution (UMA Optimistic Oracle)
- docs.polymarket.com/advanced/neg-risk
- docs.polymarket.com/api-reference/introduction
- docs.polymarket.com/market-data/websocket/overview