Skip to content

100% server-side order cancellation on POLY_1271 deposit wallet — all client-side causes ruled out #70

Description

@sergepit

Summary

All GTC limit orders placed via @polymarket/clob-client-v2 (^1.0.6) with SignatureTypeV2.POLY_1271 are accepted by the CLOB (status: "live"), then server-cancelled ~11 seconds later. Cancel timestamps are aligned to a 5-second grid (ts mod 5000 ≈ 2547ms ±22ms), consistent with a periodic sweep worker. No cancel_reason is returned in the WS user-channel CANCELED event or via getOrder().

This has been reproduced across:

  • Multiple markets / asset IDs (non-negRisk)
  • Single order after 3-minute cooldown (not rate-limiting)
  • Fresh API key (deleted old, created via createOrDeriveApiKey())
  • Aggressive heartbeat (every 2s, all OK, 58-97ms latency)
  • With and without balance/allowance cache pulse

Environment

SDK @polymarket/clob-client-v2 ^1.0.6
Signing viem 2.46.3, SignatureTypeV2.POLY_1271 (sig_type=3)
Deposit wallet (funder) 0x3de96AD68A661FA3151C4bAB54155Ab15cD6B112
EOA signer 0xDa493A99dff8cb0C8618B5094d6758A6427bF63A
API key f711d790-5d86-8cce-7a57-19205840aa36
Exchange V2 (getVersion() = 2), contract 0xE111180000d2663C0091e4f400237545B87B996B
Host VPS, Ubuntu, Node.js

Diagnostic results (10 tests, all passing)

1. Balance & allowance

  • getBalanceAllowance(COLLATERAL) returns balance=$119.67, allowance=uint256_max
  • updateBalanceAllowance(COLLATERAL) pulse succeeds every 30s
  • Single $1.75 order (BUY @0.35 × 5) is well within balance

2. EIP-1271 on-chain verification

  • Deposit wallet IS a contract (has bytecode)
  • owner() returns our EOA (0xDa49...)
  • isValidSignature(eip712_digest, sdk_signature) on deposit wallet returns 0x1626ba7e (EIP-1271 MAGIC_VALUE) ✓
  • SDK signs with ERC-7739 nested EIP-712 wrapping (636-char signature)
  • Tested with: full SDK signature against EIP-712 digest, struct hash, and inner 65-byte ECDSA — deposit wallet validates correctly

3. Heartbeat

  • Pre-heated with 3× heartbeats before order placement
  • Aggressive 2s heartbeat interval during order lifetime — all OK (58-97ms)
  • Order still cancelled at ~13s despite continuous heartbeat
  • Conclusion: NOT a heartbeat TTL issue

4. Order version & negRisk

  • getVersion() = 2 ✓
  • getNegRisk(assetId) = false ✓ (standard market, correct exchange)

5. Account state

  • getClosedOnlyMode() = false ✓
  • Account not in close-only mode

6. isOrderScoring

  • Returns false — but this is maker rewards eligibility, NOT order validity
  • Non-scoring orders can still be matched per documentation

7. API key binding

  • deriveApiKey() returns same key f711d790 for both EOA and POLY_1271 modes
  • getApiKeys() returns the key
  • Orders ARE accepted (HMAC L2 auth passes, order goes to book with status: "live")

8. API key re-creation

  • Deleted old key, created fresh via createOrDeriveApiKey() with POLY_1271
  • Same behavior: order accepted → cancelled at ~11s

9. Cooldown test

  • Bot stopped for 3 minutes, single order placed manually
  • Still cancelled at ~11s — not rate-limiting

10. Multiple markets

  • Tested 2 different asset IDs
  • Both show 100% cancel — not market-specific

WS cancel event payload

The CANCELED event from the user channel contains:

{"status": "CANCELED", "size_matched": "0", "expiration": "0"}

No cancel_reason, cancelReason, or reason field is present.

getOrder(orderId) after cancellation also shows no cancel reason.

Hypothesis

Since all client-side verification passes (EIP-1271 valid, balance sufficient, allowances max, heartbeat healthy, API key valid), the cancellation must be triggered by server-side logic that we cannot inspect. Possible causes:

  1. sum_of_matched_orders counter (ref: py-clob-client-v2 fix: preserve structured errors in paginated methods #34) — internal counter tracking matched volume may have accumulated from prior UI trades (account has 11 positions). If this counter exceeds the balance, the sweep would cancel new orders. We cannot read or reset this counter from the client side.

  2. Server-side EIP-1271 re-verification with different chain state — the sweep worker may re-verify signatures differently than the initial placement validator.

  3. Internal account flag — V2 migration may have left an account-level flag that blocks new order persistence.

Request

  1. Can you inspect the server-side cancel reason for orders from funder 0x3de96AD68A661FA3151C4bAB54155Ab15cD6B112?
  2. Is there a way to read/reset the sum_of_matched_orders counter via API?
  3. Does the 5s-grid sweep worker expose its cancel reason in any way we can access?

Related issues

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions