Polymarket version numbers are getting harder to talk about casually.

You can see:

V1 V2 V3 PolyV2 

and assume there is one protocol that simply moved from version 1 to version 2 and then version 3.

That is not how the current stack is organized.

There are different versions for different parts of the system:

Exchange Order signing Position protocol Market metadata Data APIs SDK packages 

That distinction matters when you maintain a trading bot.

A package upgrade might be trivial.

A protocol change can affect:

Contracts Collateral Order structure EIP-712 signing Asset identifiers Execution Settlement State reconciliation 

The April 2026 Polymarket exchange upgrade was a coordinated change to the smart contracts, order-book system, and collateral layer. Polymarket describes the upgrade as moving to CTF Exchange V2 and pUSD, with changes to order structure, matching, fees, and order management.

Since then, the protocol surface has continued to evolve.

The current official clients now distinguish token-backed V1/V2 flows from PolyV2 position-backed V3 flows.

For someone maintaining a Polymarket trading system, that means protocol compatibility needs to be treated as part of the infrastructure.

There is no single Polymarket "version"

This is the first thing worth getting straight.

A useful mental model is:

Polymarket │ ├── Exchange protocol │ ├── Order signing │ ├── Position protocol │ ├── Market metadata │ ├── Data services │ └── SDK packages 

Those layers can evolve independently.

For example, the current official Rust CLOB client documents:

V1 V2 V3 

as protocol variants for order construction.

Its README describes V1 as the legacy CTF-token path, V2 as the current CTF-token exchange path, and V3 as the Exchange V3 path used for Polymarket V2 positions.

That is very different from saying:

API version = 3 

There is no reason to add /v3 to every Polymarket endpoint just because Exchange V3 exists.

The versions belong to different layers.

CLOB / Exchange V2 is a real protocol change

The April 28, 2026 upgrade was not just a new SDK release.

Polymarket changed the exchange stack itself.

The official migration announcement describes three coordinated changes:

New smart contracts + Rewritten order book + New collateral token 

The new exchange contracts are CTF Exchange V2, and the new collateral token is pUSD, replacing USDC.e as the trading collateral layer.

The contract repository describes CTF Exchange V2 as the core smart-contract system for trading Conditional Token Framework assets. It currently lists the deployed Polygon contracts for the collateral token, collateral adapters, standard exchange, and negative-risk exchange.

This matters because an integration that only changes its Python or TypeScript dependency is not necessarily migrated.

The underlying assumptions may also have changed.

The order structure changed

One of the clearest examples is the signed order itself.

The current Rust client defines separate order structures for V1 and V2.

The V1 structure contains fields such as:

taker nonce feeRateBps expiration 

The V2 order structure instead uses fields including:

timestamp metadata builder 

with expiration carried separately in the payload.

The EIP-712 domain version also changes:

V1 → "1" V2 → "2" V3 → "3" 

That is not cosmetic.

The exchange contract and signed typed-data structure have to agree.

A bot that manually constructs EIP-712 messages therefore needs to know which protocol it is signing for.

Contract addresses are part of the migration

A protocol migration also changes the contracts that the trading system ultimately interacts with.

The current CTF Exchange V2 repository lists these Polygon contracts:

CTFExchangeV2 0xE111180000d2663C0091e4f400237545B87B996B NegRiskCtfExchangeV2 0xe2222d279d744050d28e00520010520000310F59 CollateralToken proxy 0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB CtfCollateralAdapter 0xADa100874d00e3331D00F2007a9c336a65009718 NegRiskCtfCollateralAdapter 0xAdA200001000ef00D07553cEE7006808F895c6F1 

These are documented by the official V2 exchange repository.

For a trading bot, hardcoded contract addresses are therefore part of the compatibility surface.

So are:

verifying contracts allowances collateral handling settlement assumptions 

A migration audit should look for all of them.

pUSD is part of the protocol change

The collateral model also changed.

Polymarket's April 2026 upgrade introduced pUSD, an ERC-20 collateral token on Polygon backed 1:1 by USDC. The exchange documentation describes pUSD as the new technical collateral layer while trading settles in native USDC.

That creates another compatibility boundary:

Old USDC.e ↓ CTF / Exchange New USDC / pUSD ↓ Collateral layer ↓ CTF / Exchange 

A bot that checks balances, approves contracts, wraps collateral, or manages inventory directly onchain needs to understand that layer.

This becomes especially important for systems that are not simply using the web interface but are managing their own wallet flow.

Fees also moved closer to protocol state

Another important change is fee handling.

Polymarket's current fee documentation says fees are applied at match time, not included as a fee field in the order itself. The current formula is based on share count, fee rate, and share price.

That means a trading system should avoid treating:

fee = property of order creation 

as a universal assumption.

Instead, it should think more like:

Order ↓ Match ↓ Protocol determines fee ↓ Execution result 

This matters for analytics as well.

If you're measuring:

Gross PnL Fees Net PnL 

the accounting layer needs to correspond to the actual execution model.

It also matters for strategy selection because Polymarket currently charges taker fees on several market categories while makers are not charged fees and can receive rebates.

Then there is PolyV2

This is where version naming gets even more confusing.

The current Polymarket clients support PolyV2 position identifiers.

These are not simply another name for normal CTF token IDs.

The official Python SDK changelog shows the progression:

0.8.0 → expose market protocol versions 0.9.0 → support Poly V2 identifiers and trading 0.10.0 → migrate data reads to Data API v2 

These are SDK changes, but they reflect underlying protocol concepts that the application has to understand.

The official Python models explicitly expose market protocol versions as:

v1 v2 

and distinguish those values from the package version itself.

PolyV2 orders use Exchange V3

This is probably the easiest place for a developer to make the wrong assumption.

The current official Rust CLOB client documents:

CTF token ↓ V2 exchange flow Polymarket V2 position ↓ V3 exchange flow 

Position-backed orders bypass the normal protocol lookup and use Exchange V3, with EIP-712 domain version "3".

The TypeScript CLOB V2 release also added support for positionID and explicitly says that it selects Exchange V3 signing for limit and market orders.

So a trading system should not simply ask:

"What version of Polymarket am I using?" 

It should ask:

What asset am I trading? What protocol does that asset use? Which exchange signs that order? Which contract verifies it? What collateral path applies? How is the resulting execution reported? 

That is a much better compatibility model.

Execution changed too

Protocol upgrades don't stop at signing.

The execution path itself has also changed.

The official Rust CLOB changelog records a July 2026 change for an asynchronous execution pipeline in which matched orders can return tradeIDs while transaction hashes are resolved later. The client added internal transaction-hash resolution for this flow.

That changes how a bot should model execution.

Instead of:

ORDER ↓ FILLED ↓ TRANSACTION HASH 

you may need:

ORDER ↓ MATCHED ↓ TRADE ID ↓ TRANSACTION RESOLUTION ↓ CONFIRMATION ↓ SETTLEMENT 

That is directly related to the execution-verification architecture I've been working on.

A match tells you something important.

It does not necessarily represent the final state of the entire execution lifecycle.

Why this matters for reconciliation

This is where protocol knowledge becomes operational engineering.

Suppose your local system records:

Order: MATCHED 

but the transaction is still unresolved.

Or:

Local position: +100 

while the remote position is:

+40 

Or the market changes protocol representation while your application still has older assumptions in memory.

The recovery problem is the same:

Local assumptions ↓ Current protocol state ↓ Compare ↓ Reconcile ↓ Verify 

Protocol-awareness therefore belongs inside the state and execution layers.

It is not something you check once during installation.

What a protocol-aware trading bot should track

I would keep protocol information explicit in the system.

For example:

Market ↓ Protocol version ↓ Asset identifier ↓ Exchange path ↓ Signing version ↓ Contract ↓ Collateral ↓ Execution state ↓ Settlement state 

That can be represented as internal metadata rather than scattered assumptions.

For example:

asset_type protocol_version position_id token_id exchange_version chain_id verifying_contract collateral_type 

The exact schema will depend on the implementation.

The important part is not hiding these distinctions.

Don't build version logic around package versions

A common mistake is:

SDK v0.10 → therefore protocol v2 

That is not a safe relationship.

The official Python SDK is currently on its own semantic versioning track, with the package at 0.12.0 in the repository metadata, while its changelog separately records support for market protocol versions, PolyV2 identifiers, and Data API v2.

Likewise, the dedicated CLOB V2 TypeScript package has its own release numbers such as 1.2.0.

These numbers describe software releases.

They do not define the onchain protocol.

What I would check before deploying a Polymarket bot

For an existing system, I would treat this as a compatibility audit.

[ ] Exchange contract addresses [ ] EIP-712 domain version [ ] Signed order fields [ ] Asset identifiers [ ] Protocol version metadata [ ] Collateral path [ ] Token / position approvals [ ] Fee handling [ ] Order submission [ ] Execution events [ ] Trade IDs [ ] Transaction resolution [ ] Settlement tracking [ ] Position reconciliation [ ] WebSocket recovery [ ] Restart recovery 

If any of these are hardcoded assumptions, the system is carrying protocol risk.

This is also why migrations should be tested end to end

I would not consider a migration complete because:

npm install 

or:

pip install 

succeeds.

The useful test is closer to:

Market discovery ↓ Protocol detection ↓ Asset identification ↓ Order construction ↓ Signature ↓ Submission ↓ Match / fill ↓ Transaction ↓ Settlement ↓ Position ↓ PnL / fee accounting 

That tests the actual system boundary.

It also gives you a much better way to catch protocol mismatches before they become trading incidents.

My current architecture

This is the direction I'm taking with my own Polymarket infrastructure work:

 POLYMARKET │ ▼ Protocol / Market │ ▼ Market Adapter │ ▼ Strategy │ ▼ Risk │ ▼ Execution │ ▼ Execution Verifier │ ▼ Reconciliation │ ▼ Control Plane │ ┌────────┴────────┐ ↓ ↓ Monitoring Recovery 

The point is to keep protocol-specific assumptions close to the integration boundary.

The rest of the system can then work with clearer internal concepts:

Order Fill Position Exposure Risk Execution status System health 

That makes future migrations easier to reason about.

The bigger lesson

Polymarket protocol changes are not really a problem for the SDK alone.

They're an integration problem.

A protocol upgrade can affect:

Contracts Signing Collateral Orders Execution Settlement Accounting State 

And those changes eventually show up as operational problems:

orders stop submitting fills become harder to interpret positions drift retries become unsafe accounting changes reconciliation breaks 

That is why I think protocol compatibility should be treated as part of trading infrastructure.

Not as a dependency upgrade.

Final takeaway

When someone says:

“Polymarket V2”

I would now ask:

V2 which layer? 

Because today you may be dealing with:

CTF Exchange V2 CLOB V2 PolyV2 positions Exchange V3 Data API V2 SDK versions 

Those are related, but they are not interchangeable labels.

For a trading bot, the useful model is:

Protocol ↓ Asset ↓ Exchange ↓ Signing ↓ Execution ↓ Settlement ↓ Position ↓ Risk 

That is the level at which compatibility actually matters.

And for an existing trading system, the practical question is not whether the latest SDK installs.

It is whether the complete path still agrees:

contracts → signing → order → match → execution → settlement → position → risk 

That is what I would test before trusting the bot with capital.