1. Bot Identity
| Layer | Execution Execution |
|---|
| Bot class | Execution Utility |
|---|
| Authority | Reshape |
|---|
| Status | LIVE |
|---|
| Readiness | General live |
|---|
| Runs before | Order submission to CLOB V2 (cancel-replace actions) |
|---|
| Runs after | NonceShepherd (nonce assigned) and SmartRouter (ExecutionPlan assembled) |
|---|
| Applies to | All resting maker orders on Polymarket CLOB V2 that are subject to quote drift or TTL management |
|---|
| Default mode | general_live |
|---|
| User-visible | Advanced details only |
|---|
| Developer owner | Polytraders core |
|---|
Operational profile
| Modes supported | quarantine |
|---|
2. Purpose
QueueWarden polices the rate at which orders and cancel-replace operations are sent to the Polymarket CLOB V2 and manages the maker queue position of resting orders. It enforces a cap on cancel-replace operations per minute to avoid CLOB rate-limit rejections, monitors drift between the resting quote price and the best bid/ask, and cancels stale resting orders that have not been filled within the stale_ttl_s window. QueueWarden also injects builderCode (bytes32) into cancel-replace messages to maintain builder attribution continuity across order lifecycle events.
3. Why This Bot Matters
Excessive cancel-replace rate
Polymarket CLOB V2 enforces per-API-key rate limits. Exceeding them causes 429 rejections, breaking the order submission pipeline and potentially leaving the strategy with unintended open positions.
Quote drift not corrected
A resting order priced more than drift_ticks_threshold ticks away from the current best bid/ask is no longer competitive; it accumulates adverse-selection risk without filling.
Stale resting order not cancelled
An order sitting in the book beyond stale_ttl_s may fill at a price that no longer reflects the strategy's current view, creating unintended exposure.
builderCode absent from cancel-replace message
Builder attribution is broken for the replacement order; maker rebates may not be correctly attributed.
No worked examples on this bot yet. Worked examples are optional but strongly recommended — they turn an abstract failure mode into something a developer can verify in a fixture.
6. Parameter Guide
| Parameter | Default | Warning | Hard | What it controls |
|---|
| drift_ticks_threshold | 2 | 3 | 5 | Maximum number of ticks a resting order's price may drift from the current best bid/ask before QueueWarden triggers a cancel-replace. |
| stale_ttl_s | 300 | 240 | 600 | Maximum seconds a resting order may sit in the CLOB book without being filled or refreshed before QueueWarden cancels it. |
| cancel_replace_per_min_cap | 30 | 24 | 30 | Maximum cancel-replace operations permitted per minute across all resting orders. Operations above this rate are queued and deferred to the next second. |
| min_queue_position | 5 | 8 | 10 | Minimum acceptable maker queue position (1 = front of queue). If the resting order's queue position worsens beyond this threshold, a cancel-replace is triggered to re-enter the front of the book. |
7. Detailed Parameter Instructions
drift_ticks_threshold
What it means
Maximum number of ticks a resting order's price may drift from the current best bid/ask before QueueWarden triggers a cancel-replace.
Default
{ "drift_ticks_threshold": 2 }
Why this default matters
A 2-tick tolerance prevents excessive cancel-replace churn on minor market movements while ensuring the quote remains competitive.
Threshold logic
| Condition | Action |
|---|
| drift <= 2 ticks | No action — order remains in book |
| 2 < drift <= 3 ticks | WARN — approaching drift limit; log for monitoring |
| 3 < drift <= 5 ticks | Trigger cancel-replace (RESHAPE) |
| drift > 5 ticks (hard) | Immediate cancel-replace regardless of rate cap |
Developer check
if drift > params.hard: force_cancel_replace(order_id)
User-facing English
Your resting order was updated to stay competitive with the current market price.
stale_ttl_s
What it means
Maximum seconds a resting order may sit in the CLOB book without being filled or refreshed before QueueWarden cancels it.
Default
{ "stale_ttl_s": 300 }
Why this default matters
A 5-minute TTL ensures stale quotes based on outdated strategy signals are removed before they fill at an adverse price.
Threshold logic
| Condition | Action |
|---|
| resting_time <= 300s | No action |
| 300 < resting_time <= 240s warning | WARN — approaching stale TTL |
| resting_time > 300s default | Cancel order — QUEUE_WARDEN_STALE_ORDER |
| resting_time > 600s hard | Force cancel regardless of rate cap |
Developer check
if order.resting_s > params.hard: force_cancel(order_id)
User-facing English
A resting order that had been waiting too long was cancelled to prevent it from filling at an outdated price.
cancel_replace_per_min_cap
What it means
Maximum cancel-replace operations permitted per minute across all resting orders. Operations above this rate are queued and deferred to the next second.
Default
{ "cancel_replace_per_min_cap": 30 }
Why this default matters
Polymarket CLOB V2 rate limits are per API key. Staying at or below 30 per minute provides headroom for fill acknowledgements and order status polling.
Threshold logic
| Condition | Action |
|---|
| rate <= 24/min | Normal operation |
| 24 < rate <= 30/min | WARN — approaching rate cap |
| rate > 30/min | Queue excess ops — QUEUE_WARDEN_RATE_CAP_HIT |
Developer check
if sliding_window_count(60) >= params.hard: defer_to_next_slot(op)
User-facing English
— not yet authored —
min_queue_position
What it means
Minimum acceptable maker queue position (1 = front of queue). If the resting order's queue position worsens beyond this threshold, a cancel-replace is triggered to re-enter the front of the book.
Default
{ "min_queue_position": 5 }
Why this default matters
Queue position 5 or better ensures the order is near the front of the maker queue, improving fill probability without triggering constant churn.
Threshold logic
| Condition | Action |
|---|
| queue_position <= 5 | No action — position acceptable |
| 5 < queue_position <= 8 | WARN — position degrading |
| 8 < queue_position <= 10 | Cancel-replace to re-enter queue at front |
| queue_position > 10 | Immediate cancel-replace regardless of rate cap |
Developer check
if queue_pos > params.hard: force_cancel_replace(order_id)
User-facing English
Your order was refreshed to maintain a competitive position in the market.
8. Default Configuration
{
"bot_id": "exec.queue_warden",
"version": "2.1.0",
"mode": "general_live",
"defaults": {
"drift_ticks_threshold": 2,
"stale_ttl_s": 300,
"cancel_replace_per_min_cap": 30,
"min_queue_position": 5
},
"locked": {
"cancel_replace_per_min_cap": {
"max": 30
},
"stale_ttl_s": {
"max": 600
}
}
}
9. Implementation Flow
- On each evaluation tick (configurable, default 5s), load the active resting order registry from internal state.
- For each resting order, fetch the current best bid/ask from the CLOB V2 authenticated book endpoint.
- Compute price drift in ticks: drift = abs(order.price - best_bid_or_ask) / tick_size.
- Compute resting time: resting_s = (now_ms() - order.placed_at_ms) / 1000.
- Fetch queue position for the order from the CLOB V2 order status endpoint.
- Apply stale TTL check: if resting_s > stale_ttl_s (or > hard limit), mark order for cancellation.
- Apply drift check: if drift > drift_ticks_threshold (or > hard limit), mark order for cancel-replace.
- Apply queue position check: if queue_position > min_queue_position (or > hard limit), mark order for cancel-replace.
- For each marked order: check sliding-window cancel-replace rate counter; if < cancel_replace_per_min_cap, execute cancel-replace immediately.
- If rate cap reached: queue excess cancel-replace ops for the next available slot; emit WARN QUEUE_WARDEN_RATE_CAP_HIT.
- On cancel-replace execution: inject builderCode (bytes32) into the replacement order payload before forwarding to NonceShepherd.
- Update internal order registry with new order_id, price, placed_at_ms after successful cancel-replace.
- Emit QueueDecision record for each evaluated order with verdict (HOLD / CANCEL_REPLACE / CANCEL_STALE) and reason_code.
10. Reference Implementation
On each evaluation tick, QueueWarden inspects every resting order in the internal registry, computes drift and resting time, and emits a QueueDecision (HOLD / CANCEL_REPLACE / CANCEL_STALE). Cancel-replace ops inject builderCode (bytes32) and are rate-limited by a sliding window counter.
Pseudocode is language-agnostic. FETCH = read input. EMIT = produce output. Translate to TS/Python/Go/Rust.
FUNCTION evaluateOrders():
// --- 0. Load active orders ---
orders = FETCH internal.order_registry.all_resting()
IF orders IS NULL:
EMIT WARN QUEUE_WARDEN_STATE_UNAVAILABLE
RETURN
// --- 1. Fetch rate counter ---
rate_1m = FETCH internal.rate_counter.sliding_window_count(60) // ops in last 60s
FOR order IN orders:
// --- 2. Fetch best bid/ask from CLOB V2 ---
book = FETCH clob_auth.GET('/book?token_id=' + order.token_id)
IF book IS NULL:
// Safe fallback: cancel rather than leave resting with unknown drift
EMIT QueueDecision(order, CANCEL_STALE, QUEUE_WARDEN_BOOK_UNAVAILABLE)
CONTINUE
best_price = book.best_ask IF order.side == 'BUY' ELSE book.best_bid
drift_ticks = abs(order.price - best_price) / order.tick_size
resting_s = (now_ms() - order.placed_at_ms) / 1000
// --- 3. Queue position check ---
queue_pos = FETCH clob_auth.GET('/order/' + order.order_id + '/queue_position')
// --- 4. Determine action ---
force = (drift_ticks > params.drift_ticks_threshold_hard
OR resting_s > params.stale_ttl_s_hard
OR queue_pos > params.min_queue_position_hard)
IF resting_s > params.stale_ttl_s:
action = 'CANCEL_STALE'; reason = 'QUEUE_WARDEN_STALE_ORDER'
ELSE IF drift_ticks > params.drift_ticks_threshold:
action = 'CANCEL_REPLACE'; reason = 'QUEUE_WARDEN_DRIFT_EXCEEDED'
ELSE IF queue_pos > params.min_queue_position:
action = 'CANCEL_REPLACE'; reason = 'QUEUE_WARDEN_QUEUE_DEGRADED'
ELSE:
// HOLD — possibly with WARN annotation
warn = (drift_ticks > params.drift_ticks_threshold - 1
OR resting_s > params.stale_ttl_s * 0.8)
EMIT QueueDecision(order, HOLD, None, warn=warn)
CONTINUE
// --- 5. Rate-cap check ---
IF action == 'CANCEL_REPLACE' AND rate_1m >= params.cancel_replace_per_min_cap AND NOT force:
internal.rate_queue.enqueue(order.order_id, action)
EMIT WARN QUEUE_WARDEN_RATE_CAP_HIT
CONTINUE
// --- 6. Execute cancel ---
clob_auth.DELETE('/order/' + order.order_id)
internal.order_registry.remove(order.order_id)
IF action == 'CANCEL_REPLACE':
// --- 7. Build replacement with V2 fields + builderCode ---
replacement = {
market_id: order.market_id,
side: order.side,
price: best_price, // refreshed to current best
size_usd: order.size_usd,
builder_code: config.builder_code, // bytes32
eip712_domain_version: '2'
}
// Nonce assigned by NonceShepherd before signing
EMIT NonceAssignmentRequest(replacement)
internal.rate_counter.increment()
EMIT QueueDecision(order, action, reason,
drift_ticks=drift_ticks, resting_s=resting_s,
queue_position=queue_pos,
builder_code=config.builder_code,
evaluated_at_ms=now_ms())
SDK calls used
clob_auth.GET('/book?token_id=' + order.token_id)clob_auth.GET('/order/' + order.order_id + '/queue_position')clob_auth.DELETE('/order/' + order.order_id)clob_auth.POST('/order', signed_replacement_order)buildOrderTypedData(replacementParams, { name: 'CTFExchange', version: '2', chainId: 137 })
Complexity: O(R) where R = number of resting orders in the registry per evaluation tick
11. Wire Examples
Input — what arrives on the wire
{
"label": "Resting order evaluated for drift",
"source": "internal order registry + CLOB V2 book snapshot",
"payload": {
"order_id": "0xb2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3",
"market_id": "0x9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c",
"side": "BUY",
"outcome": "YES",
"price": 0.65,
"tick_size": 0.01,
"size_usd": 200,
"placed_at_ms": 1746769153000,
"best_ask_at_eval": 0.68,
"queue_position": 4
}
}
Output — what the bot emits
{
"label": "QueueDecision — CANCEL_REPLACE due to drift",
"payload": {
"warden_id": "exec.queue_warden",
"order_id": "0xb2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3",
"market_id": "0x9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c",
"verdict": "CANCEL_REPLACE",
"reason_code": "QUEUE_WARDEN_DRIFT_EXCEEDED",
"drift_ticks": 3,
"resting_s": 47,
"queue_position": 4,
"replacement_price": 0.68,
"builder_code": "0x706f6c7974726164657273000000000000000000000000000000000000000000",
"eip712_domain_version": "2",
"evaluated_at_ms": 1746769200000
}
}
12. Decision Logic
APPROVE
Order is within drift tolerance, below stale TTL, and queue position is acceptable. QueueDecision.HOLD emitted.
RESHAPE_REQUIRED
Drift exceeds threshold or queue position has degraded past min_queue_position. QueueDecision.CANCEL_REPLACE emitted; replacement order constructed with refreshed price and builderCode.
REJECT
Resting order has exceeded stale_ttl_s. QueueDecision.CANCEL_STALE emitted; order cancelled with no replacement.
WARNING_ONLY
Drift or resting time is in the warning band but below the action threshold. WARN annotation on QueueDecision.HOLD.
13. Standard Decision Output
This bot returns a QueueDecision object. See QueueDecision schema.
{
"warden_id": "exec.queue_warden",
"order_id": "0xb2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3",
"market_id": "0x9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c",
"verdict": "CANCEL_REPLACE",
"reason_code": "QUEUE_WARDEN_DRIFT_EXCEEDED",
"drift_ticks": 3,
"resting_s": 47,
"queue_position": 4,
"replacement_price": 0.68,
"builder_code": "0x706f6c7974726164657273000000000000000000000000000000000000000000",
"eip712_domain_version": "2",
"evaluated_at_ms": 1746769200000
}
14. Reason Codes
| Code | Severity | Meaning | Action | User-facing message |
|---|
QUEUE_WARDEN_HOLD | INFO | Resting order is within drift tolerance, below stale TTL, and queue position is acceptable. | No action. Emit QueueDecision.HOLD. | |
QUEUE_WARDEN_DRIFT_EXCEEDED | RESHAPE | Order price has drifted more than drift_ticks_threshold ticks from the current best bid/ask. | Cancel and replace order at current best price with refreshed builderCode. | Your resting order was updated to align with the current market price. |
QUEUE_WARDEN_STALE_ORDER | RESHAPE | Resting order has exceeded stale_ttl_s without being filled. | Cancel order without replacement. Emit QueueDecision.CANCEL_STALE. | A resting order was cancelled because it had been waiting too long without being filled. |
QUEUE_WARDEN_QUEUE_DEGRADED | RESHAPE | Maker queue position has worsened beyond min_queue_position threshold. | Cancel and replace to re-enter at the front of the queue. | Your order was refreshed to maintain a competitive position in the market. |
QUEUE_WARDEN_RATE_CAP_HIT | WARN | cancel_replace_per_min_cap has been reached; excess operations are queued for the next rate window. | Enqueue op in rate-deferred queue. Emit WARN. Do not block non-cancel-replace ops. | |
QUEUE_WARDEN_BOOK_UNAVAILABLE | HARD_REJECT | CLOB V2 book endpoint is unreachable; drift cannot be computed for this order. | Cancel order as safe fallback. Emit QueueDecision.CANCEL_STALE. | A resting order was cancelled because market data was temporarily unavailable. |
QUEUE_WARDEN_STATE_UNAVAILABLE | HARD_REJECT | Internal order registry is unreachable; evaluation cannot proceed. | Pause all evaluation. Emit WARN. Resume when state store reconnects. | |
KILL_SWITCH_ACTIVE | HARD_REJECT | Global kill switch is active; all resting orders are cancelled immediately. | Cancel all resting orders. Emit no replacement orders. | Trading is currently paused. |
15. Metrics & Logs
Metrics emitted
| Metric | Type | Unit | Labels | Meaning |
|---|
polytraders_exec_queuewarden_decisions_total | counter | count | verdict, reason_code | Total QueueDecision records emitted per verdict and reason code. |
polytraders_exec_queuewarden_cancel_replace_rate_1m | gauge | count | | Sliding 60-second cancel-replace operation rate; alert when approaching cap. |
polytraders_exec_queuewarden_drift_ticks | histogram | ticks | market_id | Distribution of drift in ticks across all evaluated orders; >2 ticks triggers CANCEL_REPLACE. |
polytraders_exec_queuewarden_resting_time_seconds | histogram | seconds | | Distribution of resting time across all evaluated orders; >stale_ttl_s triggers cancellation. |
polytraders_exec_queuewarden_rate_queue_depth | gauge | count | | Number of cancel-replace ops currently deferred in the rate queue. |
polytraders_exec_queuewarden_eval_latency_ms | histogram | ms | | Wall-clock time to complete one full evaluation tick across all resting orders. |
Alerts
| Alert | Condition | Severity | Runbook |
|---|
QueueWardenRateCapPersistent | polytraders_exec_queuewarden_cancel_replace_rate_1m >= 28 | warn | #runbook-queuewarden-rate-cap |
QueueWardenRateQueueDeep | polytraders_exec_queuewarden_rate_queue_depth > 20 | warn | #runbook-queuewarden-rate-queue-deep |
QueueWardenBookUnavailable | rate(polytraders_exec_queuewarden_decisions_total{reason_code='QUEUE_WARDEN_BOOK_UNAVAILABLE'}[5m]) > 0.1 | page | #runbook-queuewarden-book-unavailable |
QueueWardenHighDrift | histogram_quantile(0.95, rate(polytraders_exec_queuewarden_drift_ticks_bucket[5m])) > 3 | warn | #runbook-queuewarden-high-drift |
Dashboards
- Grafana — Execution / QueueWarden
- Grafana — Order quality / drift distribution and stale order rate
16. Developer Reporting
{
"warden_id": "exec.queue_warden",
"order_id": "0xb2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3",
"market_id": "0x9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c",
"order_price": 0.65,
"best_ask": 0.68,
"drift_ticks": 3,
"drift_ticks_threshold": 2,
"resting_s": 47,
"stale_ttl_s": 300,
"queue_position": 4,
"min_queue_position": 5,
"cancel_replace_rate_1m": 12,
"cancel_replace_per_min_cap": 30,
"verdict": "CANCEL_REPLACE",
"reason_code": "QUEUE_WARDEN_DRIFT_EXCEEDED",
"builder_code": "0x706f6c7974726164657273000000000000000000000000000000000000000000",
"evaluated_at_ms": 1746769200000
}
17. Plain-English Reporting
| Situation | User-facing explanation |
|---|
| Resting order price updated | Your resting order was refreshed to stay aligned with the current market price. |
| Stale resting order cancelled | A resting order that had been waiting longer than the allowed window was cancelled to prevent it from filling at an outdated price. |
| Order update queued — high activity | A minor order update is queued briefly due to high activity. It will be applied within seconds. |
18. Failure-Mode Block
| main_failure_mode | Rate cap hit during a volatile period causing a backlog of cancel-replace ops. If the backlog is not drained before stale TTL expires, stale orders may fill at adverse prices before they can be cancelled. |
|---|
| false_positive_risk | Triggering a cancel-replace on a minor drift caused by a momentary price spike that immediately reverts, resulting in unnecessary churn and order management cost. |
|---|
| false_negative_risk | Failing to detect drift because the CLOB book snapshot is stale (e.g. book endpoint latency spike), allowing an order to rest at an uncompetitive price beyond the threshold. |
|---|
| safe_fallback | If the CLOB book endpoint is unreachable, cancel all resting orders as a precaution rather than leaving them with unknown drift. If the internal state store is unavailable, pause all evaluations and emit QUEUE_WARDEN_STATE_UNAVAILABLE. |
|---|
| required_dependencies | CLOB V2 authenticated book endpoint, Internal order state store (Redis), Sliding-window rate counter (Redis), NonceShepherd (for cancel-replace nonce assignment) |
|---|
19. Failure-Injection Recipes
| Scenario | How to inject | Expected behaviour | Recovery |
|---|
BOOK_ENDPOINT_DOWN | Block TCP to clob.polymarket.com on the book endpoint | | Orders re-submitted by SmartRouter on next strategy evaluation cycle after CLOB connectivity restored |
RATE_CAP_EXHAUSTED | Set cancel_replace_rate_1m counter to 30 (at cap) in Redis | | Queue drains automatically as rate window resets after 60s |
STALE_ORDER_MASS_EXPIRY | Set placed_at_ms for all registry entries to now()-310s (beyond stale_ttl_s=300) | | SmartRouter re-submits fresh orders on next strategy cycle |
BUILDER_CODE_ABSENT | Null out config.builder_code before a cancel-replace cycle | | Restore config.builder_code from secrets manager |
KILL_SWITCH_ON | Activate global KillSwitch | | Orders re-submitted after manual KillSwitch reset and strategy confirmation |
20. State & Persistence
Cold-start recovery
On restart, order registry is replayed from Redis. Any entry older than stale_ttl_s_hard is immediately cancelled. Rate counter resets on restart.
21. Concurrency & Idempotency
| Aspect | Specification |
|---|
| Execution model | single-threaded event loop |
| Max in-flight | 30 |
| Idempotency key | order_id |
| Per-call timeout (ms) | 1000 |
| Backpressure strategy | Excess cancel-replace ops queued in rate-deferred queue; evaluation tick skipped if previous tick has not completed |
| Locking / mutual exclusion | Redis SETNX per order_id during cancel-replace execution to prevent double-cancel |
22. Dependencies
Depends on (must run first)
| Bot | Why | Contract |
|---|
| exec.smart_router | SmartRouter provides replacement ExecutionPlan parameters when a cancel-replace is triggered. | Replacement order must preserve side, market_id, and outcome from original order. |
| exec.nonce_shepherd | NonceShepherd assigns the nonce and injects builderCode for every replacement order. | QueueWarden emits a NonceAssignmentRequest; NonceShepherd responds with a signed-ready payload. |
| risk.kill_switch | KillSwitch active triggers immediate cancellation of all resting orders. | On KillSwitch activation, QueueWarden cancels all resting orders and emits no replacement orders. |
Emits to (downstream consumers)
External services
| Service | Endpoint | SLA assumed | On failure |
|---|
| Polymarket CLOB V2 (auth) | https://clob.polymarket.com | 99.95% / 200ms p99 | |
23. Security Surfaces
Abuse vectors considered
- Manipulating the internal order registry to falsely report high queue positions, triggering excessive cancel-replace churn and burning through the rate cap
- Injecting a false book snapshot to inflate apparent drift and cause unnecessary order refresh operations
- Rate cap exhaustion attack: flooding QueueWarden with resting orders to exhaust cancel_replace_per_min_cap before legitimate orders can be managed
Mitigations
- Order registry write access restricted to QueueWarden and NonceShepherd service accounts via Redis ACL
- Book snapshots fetched directly from Polymarket CLOB V2 authenticated endpoint — not from an internal cache that could be tampered with
- Rate counter enforced per-key sliding window; max 30 ops/min per API key is a hard constraint on the CLOB side as well
- QueueDecision records HMAC-signed; consumers reject tampered records
24. Polymarket V2 Compatibility
| Aspect | Value |
|---|
| CLOB version | v2 |
| Collateral asset | pUSD |
| EIP-712 Exchange domain version | 2 |
| Aware of builderCode field | yes |
| Aware of negative-risk markets | no |
| Multi-chain ready | no |
| SDK used | py-clob-client-v2 |
| Settlement contract | CTFExchangeV2 |
| Notes | QueueWarden injects builderCode (bytes32) into every cancel-replace replacement order, maintaining builder attribution continuity across the order lifecycle. V2 cancel-replace does not include feeRateBps — fees are operator-set by CTFExchangeV2 at match time. EIP-712 Exchange domain version is '2'; ClobAuth domain version is '1'. |
API surfaces declared
clob_authinternal
Networks supported
polygon
25. Versioning & Migration
| Field | Value |
|---|
| spec | 2.0.0 |
| implementation | 2.1.0 |
| schema | 2 |
| released | 2026-04-28 |
Migration history
| Date | From | To | Reason | Action taken |
|---|
| 2026-04-28 | v1 | v2 | CLOB V2 cutover — order lifecycle management updated for V2 signed-order schema | Removed feeRateBps and nonce from cancel-replace order payloads (V2: operator-set fees, NonceShepherd manages nonces). Added builderCode (bytes32) injection into all replacement orders to maintain builder attribution across the full order lifecycle. Updated EIP-712 Exchange domain to version '2'. Collateral denomination updated from USDC.e to pUSD in all QueueDecision records. |
26. Acceptance Tests
Unit Tests
| Test | Setup | Expected result |
|---|
| Emit HOLD when drift is within threshold | order.price=0.65, best_ask=0.66, tick_size=0.01, drift_ticks_threshold=2 | QueueDecision.verdict=HOLD |
| Trigger CANCEL_REPLACE when drift exceeds threshold | order.price=0.65, best_ask=0.68, tick_size=0.01, drift_ticks_threshold=2 | QueueDecision.verdict=CANCEL_REPLACE, reason_code=QUEUE_WARDEN_DRIFT_EXCEEDED |
| Cancel stale order when resting_s > stale_ttl_s | order.resting_s=310, stale_ttl_s=300 | QueueDecision.verdict=CANCEL_STALE, reason_code=QUEUE_WARDEN_STALE_ORDER |
| Defer cancel-replace when rate cap is reached | cancel_replace_rate_1m=30, cancel_replace_per_min_cap=30 | Op queued for next slot; WARN QUEUE_WARDEN_RATE_CAP_HIT emitted |
| builderCode injected into replacement order | Standard cancel-replace trigger | QueueDecision.builder_code = 32-byte hex string; non-null |
Integration Tests
| Test | Expected result |
|---|
| End-to-end: drift exceeds threshold → cancel-replace → new order accepted by CLOB | Old order cancelled; replacement order with refreshed price and builderCode submitted and accepted |
| Rate cap hit: excess ops queue and drain correctly after cap window resets | Ops execute in order after rate window resets; no ops dropped |
Property Tests
| Property | Required behaviour |
|---|
| builderCode (bytes32) is always non-null on every cancel-replace replacement order | Always true — builder_code_aware=true |
| cancel_replace_per_min_cap is never exceeded in any 60-second window | Always true — sliding window enforced before any op submission |
27. Operational Runbook
QueueWarden incidents are typically rate-cap exhaustion during volatile markets, CLOB book endpoint degradation causing precautionary mass cancellations, or KillSwitch-triggered mass cancellations. All require coordination with the Strategy pod.
On-call actions
| Alert | First step | Diagnosis | Mitigation | Escalate to |
|---|
QueueWardenBookUnavailable | Verify CLOB V2 book endpoint. Check Polymarket status page. | CLOB book endpoint unreachable; all resting orders cancelled as safe fallback. Orders need re-submission. | Restore CLOB connectivity. Notify Strategy pod to re-submit resting orders. | Exec pod lead and Strategy pod — orders need re-submission after CLOB recovery |
QueueWardenRateCapPersistent | Check cancel-replace rate in Grafana. If market volatility is causing rapid drift, reduce strategy aggressiveness temporarily. | High market volatility is triggering drift-based cancel-replace operations faster than the rate cap allows. | Reduce strategy quote refresh aggressiveness or request a temporary rate cap increase. | Strategy pod lead if rate cap sustained > 5 minutes |
QueueWardenRateQueueDeep | Rate queue depth > 20 means many updates are deferred. Check if rate cap can be increased temporarily. | Deferred cancel-replace ops are accumulating; some orders may become stale before they can be refreshed. | Request rate cap increase from Exec pod lead. Run: polytraders bot flush-queue exec.queue_warden --rate after cap is raised. | Exec pod lead for rate cap increase approval |
QueueWardenHighDrift | High drift p95 > 3 ticks indicates market is moving faster than the evaluation tick. Check evaluation_tick_s config and CLOB latency. | Evaluation tick interval may be too slow for current market volatility, or CLOB latency is causing stale book snapshots. | Reduce evaluation_tick_s. Check CLOB book endpoint latency. | Strategy pod lead if sustained > 10 minutes |
Manual overrides
polytraders bot cancel-all exec.queue_warden — Immediately cancels all resting orders without waiting for the next evaluation tick. Use in emergencies.polytraders bot flush-queue exec.queue_warden --rate — Force-drains the rate-deferred cancel-replace queue after the rate cap is raised or market calms.
Healthcheck
GET /internal/health/queuewarden → 200 if CLOB book endpoint reachable, cancel_replace_rate_1m < 24, rate queue depth < 10, state store connected. RED if CLOB unreachable, rate_1m >= 30, or state store disconnected.
29. Developer Checklist
Ready-to-ship score: 27/27 sections complete · 100%
| Requirement | Status |
|---|
| Purpose defined | ✓ done |
| Required inputs listed | ✓ done |
| Parameters defined | ✓ done |
| Defaults defined | ✓ done |
| Warning thresholds defined | ✓ done |
| Hard thresholds defined | ✓ done |
| Safe fallback defined | ✓ done |
| Structured output defined | ✓ done |
| Developer log defined | ✓ done |
| Plain-English explanation | ✓ done |
| Unit tests defined | ✓ done |
| Integration tests defined | ✓ done |
| Property tests defined | ✓ done |
| Failure-mode block complete | ✓ done |
| Reference implementation pseudocode | ✓ done |
| Wire examples (input + output) | ✓ done |
| Reason codes listed | ✓ done |
| Metrics & logs defined | ✓ done |
| State & persistence defined | ✓ done |
| Concurrency & idempotency defined | ✓ done |
| Dependencies declared | ✓ done |
| Security surfaces declared | ✓ done |
| Polymarket V2 compatibility declared | ✓ done |
| Version & migration history declared | ✓ done |
| Operational runbook defined | ✓ done |
| Promotion gates defined | ✓ done |
| Failure-injection recipes defined | ✓ done |