Polytraders Dev Guide
internal
v3 spine Phase 1 · Shared contracts 9 demo-wired · 0 shadow-ready · 0 production-live · 100 pending · 109 total 15/33 infra tasks the plan status board
HomeBy LayerGovernance6.1 BuilderAttribution

6.1 BuilderAttribution

Governance Governance Service Explain LIVE General live capital · Indirect P3 · Reporting & event store pending flagship reference bot

BuilderAttribution tags every outgoing order with the Polytraders builder code before submission, logs each fill against the builder code, and reconciles the local fill log against the Polymarket builder-code report every 24 hours. If a discrepancy is detected — missing attribution, volume drift, or order counts that do not match — it quarantines the affected records and raises an alert. BuilderAttribution never submits, modifies, or cancels orders. Its authority is to explain and audit only.

v3 readiness

Docs27/27
donehow scored
Impl0/15
pendinghow scored
Backtest0/4
pendinghow scored
Runtime0/8
pendinghow scored

A bot is done when all four scores are. What does done mean?

1. Bot Identity

LayerGovernance  Governance
Bot classGovernance Service
AuthorityExplain
StatusLIVE
ReadinessGeneral live
Runs beforeNothing — runs post-trade on every fill event
Runs afterOrder submission and fill confirmation
Applies toEvery filled or partially filled order, and every daily reconciliation window
Default modegeneral_live
User-visibleAdvanced details only
Developer ownerPolytraders core — Governance pod

2. Purpose

BuilderAttribution tags every outgoing order with the Polytraders builder code before submission, logs each fill against the builder code, and reconciles the local fill log against the Polymarket builder-code report every 24 hours. If a discrepancy is detected — missing attribution, volume drift, or order counts that do not match — it quarantines the affected records and raises an alert. BuilderAttribution never submits, modifies, or cancels orders. Its authority is to explain and audit only.

3. Why This Bot Matters

  • Builder code missing from an outgoing order

    Volume attributed to the builder is undercounted in the Polymarket report, which affects fee rebates, builder-tier status, and audit trails for compliance.

  • Daily reconciliation not performed

    Attribution drift compounds silently over time. Without regular reconciliation, discrepancies may only be discovered during a formal audit when they are much harder to investigate.

  • Quarantine not applied on drift

    Unreconciled records remain in the live ledger and may be double-counted or misreported in downstream reports if not flagged and isolated.

  • Attribution log retention not enforced

    Without a defined retention policy, old attribution records may be purged before they are needed for a historical audit or fee dispute.

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.

4. Required Polymarket Inputs

InputSourceRequired?Use
Per-fill attribution data from every submitted orderCLOBYesCapture the builder_code field on each fill confirmation and store it in the attribution log.
Polymarket builder-code volume report (rolling 24 hours)Data APIYesReconcile the local fill log against Polymarket's official attribution report each reconcile window.
Order submission acknowledgementsCLOBYesConfirm that the builder_code was accepted and echoed back in each order acknowledgement; flag any order where it is absent.

5. Required Internal Inputs

InputSourceRequired?Use
Outgoing order stream before submissionStrategyRegistryYesIntercept each order in-flight to attach the builder_code to the payload before it is signed and submitted.
KillSwitch active flagKillSwitchNoContinue logging and reconciliation even when KillSwitch is active — attribution must track all events including rejected ones.

6. Parameter Guide

ParameterDefaultWarningHardWhat it controls
builder_codepolytradersThe canonical builder code string that must be present on every outgoing order. This value is locked and can only be changed via a signed admin action.
reconcile_window_h244872How often in hours the local fill log is reconciled against the Polymarket builder-code report.
quarantine_on_driftTrueNoneNoneWhen true (locked), any fill records that do not match the Polymarket report are moved to a quarantine partition and flagged for manual review before inclusion in any downstream report.
alert_on_missing_codeTrueNoneNoneWhen true (locked), every order that arrives at the attribution layer without a builder_code field triggers an immediate alert to the monitoring stack.

7. Detailed Parameter Instructions

builder_code

What it means

The canonical builder code string that must be present on every outgoing order. This value is locked and can only be changed via a signed admin action.

Default

{ "builder_code": "polytraders" }

Why this default matters

The builder code is the immutable identifier that Polymarket uses to attribute volume and fee rebates. Any change to it must be coordinated with Polymarket and logged formally.

Threshold logic

ConditionAction
order.builder_code === builder_codeAPPROVE — log and continue
order.builder_code is absentAttach builder_code and emit MISSING_CODE alert
order.builder_code !== builder_codeReject attachment and raise PARAMETER_CHANGE_REQUIRES_APPROVAL alert

Developer check

if (!order.builder_code) { order.builder_code = p.builder_code; alerting.emit('MISSING_CODE'); }

User-facing English

Every order is tagged with an identifier that tracks your trading volume on Polymarket. This supports fee reconciliation and audit.

reconcile_window_h

What it means

How often in hours the local fill log is reconciled against the Polymarket builder-code report.

Default

{ "reconcile_window_h": 24 }

Why this default matters

A 24-hour window aligns with Polymarket's rolling report cadence. Reconciling more frequently is supported but reconciling less often than 72 hours risks missing drift until it compounds.

Threshold logic

ConditionAction
reconcile_window_h ≤ 24Reconcile at configured frequency
24–72 hWARN — drift detection is delayed
> 72 hReject config change — PARAMETER_CHANGE_REQUIRES_APPROVAL

Developer check

if (p.reconcile_window_h > p.hard) throw new ConfigError('PARAMETER_CHANGE_REQUIRES_APPROVAL');

User-facing English

Your trading activity is checked daily against the exchange's records to make sure everything is correctly attributed.

quarantine_on_drift

What it means

When true (locked), any fill records that do not match the Polymarket report are moved to a quarantine partition and flagged for manual review before inclusion in any downstream report.

Default

{ "quarantine_on_drift": true }

Why this default matters

Unreconciled records in the live ledger can corrupt downstream reports. Quarantining immediately on detection isolates the problem without data loss.

Threshold logic

ConditionAction
quarantine_on_drift=true AND drift detectedMove affected records to quarantine partition and emit reconciliation alert
quarantine_on_drift=falseNot permitted — parameter is locked to true

Developer check

if (p.quarantine_on_drift && reconciliationDrift) quarantine.move(driftedRecords);

User-facing English

If any inconsistency is found during the daily check, the affected records are set aside for review rather than being included in reports.

alert_on_missing_code

What it means

When true (locked), every order that arrives at the attribution layer without a builder_code field triggers an immediate alert to the monitoring stack.

Default

{ "alert_on_missing_code": true }

Why this default matters

A missing builder code on any order is an anomaly that should never happen in normal operation. Alerting on every occurrence ensures it is investigated immediately rather than discovered in the next reconciliation.

Threshold logic

ConditionAction
alert_on_missing_code=true AND builder_code absentAttach code and emit MISSING_CODE alert
alert_on_missing_code=falseNot permitted — parameter is locked to true

Developer check

if (p.alert_on_missing_code && !order.builder_code) alerting.emit('MISSING_BUILDER_CODE', { order_id: order.id });

User-facing English

An alert is raised any time an order is detected without the required tracking code, so it can be investigated promptly.

8. Default Configuration

{
  "bot_id": "gov.builder_attribution",
  "version": "1.0.0",
  "mode": "general_live",
  "defaults": {
    "builder_code": "polytraders",
    "reconcile_window_h": 24,
    "quarantine_on_drift": true,
    "alert_on_missing_code": true
  },
  "locked": {
    "builder_code": {
      "change_requires_signed_admin_action": true
    },
    "quarantine_on_drift": {
      "immutable": true
    },
    "alert_on_missing_code": {
      "immutable": true
    },
    "reconcile_window_h": {
      "max": 72
    }
  }
}

9. Implementation Flow

  1. Intercept every outgoing order from StrategyRegistry before it reaches the signing step; verify builder_code is present and correct.
  2. If builder_code is absent, attach the configured builder_code value and emit an alert to the monitoring stack (alert_on_missing_code).
  3. After each fill confirmation from the CLOB, extract the fill metadata (order_id, market_id, size_usd, price, side, timestamp, builder_code echoed by exchange).
  4. Append the fill record to the local attribution log with all metadata fields and a log_sequence_number for ordering.
  5. Every reconcile_window_h hours, fetch the Polymarket builder-code volume report from Data API for the matching time window.
  6. Compare local fill log totals (volume, order count, unique market count) against the Polymarket report for the same window.
  7. If discrepancy is detected: compute the drift delta, tag affected records with a quarantine flag, and move them to the quarantine partition (quarantine_on_drift).
  8. Emit a reconciliation report to the governance audit trail (GovernanceLog) whether the reconciliation passes or flags drift.
  9. Retain all attribution log records for a minimum of 90 days; quarantined records are retained indefinitely until manually reviewed and resolved.
  10. Produce a PostTradeExplanation entry for each reconciliation cycle summarising: total volume attributed, match status, drift delta if any, and quarantine record count.

10. Reference Implementation

Intercepts every outgoing order to verify the builderCode bytes32 field is present, logs each fill to the attribution ledger, and runs a 24-hour reconciliation against the Data API builder-code volume report. Quarantines drift records and emits a GovernanceLog on every cycle.

Pseudocode is language-agnostic. FETCH = read input. EMIT = produce output. Translate to TS/Python/Go/Rust.

// ---- PRE-SUBMISSION HOOK: called on every outgoing order ----
FUNCTION attachAndVerifyBuilderCode(order):
  // In V2, builderCode is a bytes32 field on the order (not HMAC)
  IF order.builder IS NULL OR order.builder == ZERO_BYTES32:
    order.builder = config.builder_code_bytes32
    alerting.emit('BUILDER_CODE_MISSING', { order_id: order.id })
  IF order.builder != config.builder_code_bytes32:
    alerting.emit('BUILDER_CODE_MISMATCH', { order_id: order.id, found: order.builder })
    raise PARAMETER_CHANGE_REQUIRES_APPROVAL
  RETURN order

// ---- POST-FILL HOOK: called on every fill confirmation ----
FUNCTION logFill(fillEvent):
  // fillEvent.builder is echoed back by CTFExchangeV2 from the on-order builderCode
  IF fillEvent.builder != config.builder_code_bytes32:
    alerting.emit('BUILDER_CODE_MISSING', { fill_id: fillEvent.fill_id })

  record = {
    fill_id:           fillEvent.fill_id,
    order_id:          fillEvent.order_id,
    market_id:         fillEvent.market_id,
    side:              fillEvent.side,
    size_pusd:         toUsdcUnits(fillEvent.size_usd),
    price:             fillEvent.price,
    builder_code:      fillEvent.builder,
    // V2 fee: builder_fee = notional * bps / 10000
    builder_fee_pusd:  toUsdcUnits(fillEvent.size_usd * fillEvent.builder_fee_bps / 10000),
    fill_confirmed_at: fillEvent.timestamp,
    log_seq:           postgres.nextval('attribution_log_seq')
  }
  postgres.INSERT('attribution_log', record)
  EMIT GovernanceLog(event_type='FILL_LOGGED', fill_id=fillEvent.fill_id)

// ---- RECONCILIATION: runs every reconcile_window_h hours ----
FUNCTION reconcile(windowStart, windowEnd):
  localRows = postgres.SELECT('attribution_log',
                WHERE fill_confirmed_at BETWEEN windowStart AND windowEnd)
  localVolume = SUM(r.size_pusd FOR r IN localRows)
  localCount  = COUNT(localRows)

  report = FETCH data_api.GET(
    '/builder-code-report?code=' + config.builder_code
    + '&from=' + windowStart + '&to=' + windowEnd
  )
  IF report IS NULL:
    alerting.emit('RECONCILIATION_SKIP', { reason: 'data_api_unavailable' })
    RETURN

  drift_usd = abs(localVolume - report.volume_pusd)
  drift_pct = drift_usd / max(localVolume, 1)

  IF drift_pct > 0.01:  // > 1% drift
    driftRows = identify_drift_rows(localRows, report)
    postgres.UPDATE('attribution_log', driftRows, { quarantined: true })
    alerting.emit('RECONCILIATION_DRIFT_OBSERVED', { drift_usd, drift_pct })
    EMIT GovernanceLog(event_type='RECONCILIATION_DRIFT',
                       drift_usd=drift_usd, quarantine_count=len(driftRows))
  ELSE:
    EMIT GovernanceLog(event_type='RECONCILIATION_COMPLETE',
                       drift_detected=False, local_volume=localVolume,
                       polymarket_volume=report.volume_pusd)

  // Retain all records >= 90 days; quarantined records retained indefinitely

Helpers used

HelperSignaturePurpose
toUsdcUnitstoUsdcUnits(rawUsd: float) -> intConverts a raw pUSD float to the 6-decimal integer unit used by CTFExchangeV2; ensures fill_log precision matches on-chain values.
fetchClobPublicfetchClobPublic(path: str) -> JSONUsed to verify fill confirmations against CLOB order status for reconciliation.
platformFeeplatformFee(notional: float, prob: float, feeRate: float) -> floatEstimates the platform fee component; logged alongside builder_fee_pusd for fee breakdown reporting.
buildOrderTypedDatabuildOrderTypedData(order, domain) -> TypedDataNot called by BuilderAttribution; referenced to confirm that builderCode bytes32 is populated by SmartRouter before this bot sees the order.

SDK calls used

  • data_api.GET('/builder-code-report?code=...&from=...&to=...')
  • clob_auth.GET('/fills?order_id=...&limit=100')
  • postgres.INSERT('attribution_log', record)
  • postgres.SELECT('attribution_log', WHERE fill_confirmed_at BETWEEN ... AND ...)
  • alerting.emit('RECONCILIATION_DRIFT_OBSERVED', metadata)

Complexity: O(F) per reconciliation window where F = fill count; O(1) per fill log event

11. Wire Examples

Input — what arrives on the wire

Fill confirmation from CTFExchangeV2clob_auth

{
  "fill_id": "fill_00a1b2c3d4e5f6a7",
  "order_id": "ord_00123",
  "market_id": "0x9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c",
  "side": "BUY",
  "size_usd": 250.0,
  "price": 0.62,
  "builder": "0x706f6c7974726164657273000000000000000000000000000000000000000000",
  "builder_fee_bps": 25,
  "fill_confirmed_at": "2026-05-09T11:45:00Z"
}

Data API builder-code volume reportdata_api

{
  "builder_code": "polytraders",
  "window_start": "2026-05-08T00:00:00Z",
  "window_end": "2026-05-09T00:00:00Z",
  "volume_pusd": 48320.5,
  "order_count": 217,
  "fill_count": 217
}

Output — what the bot emits

GovernanceLog — RECONCILIATION_COMPLETE (no drift)

{
  "attribution_id": "gov.builder_attribution",
  "event_type": "RECONCILIATION_COMPLETE",
  "window_start": "2026-05-08T00:00:00Z",
  "window_end": "2026-05-09T00:00:00Z",
  "local_volume_pusd": 48320.5,
  "polymarket_volume_pusd": 48320.5,
  "local_order_count": 217,
  "polymarket_order_count": 217,
  "drift_detected": false,
  "quarantine_count": 0,
  "builder_code": "polytraders",
  "retention_days": 90,
  "reconciled_at": "2026-05-09T00:05:12Z"
}

GovernanceLog — RECONCILIATION_DRIFT (quarantine triggered)

{
  "attribution_id": "gov.builder_attribution",
  "event_type": "RECONCILIATION_DRIFT",
  "window_start": "2026-05-08T00:00:00Z",
  "window_end": "2026-05-09T00:00:00Z",
  "local_volume_pusd": 48420.5,
  "polymarket_volume_pusd": 48320.5,
  "drift_usd": 100.0,
  "drift_pct": 0.00207,
  "drift_detected": true,
  "quarantine_count": 2,
  "reconciled_at": "2026-05-09T00:06:00Z"
}

Reproduce locally

curl 'https://data-api.polymarket.com/builder-code-report?code=polytraders&from=2026-05-08T00:00:00Z&to=2026-05-09T00:00:00Z'

12. Decision Logic

APPROVE

Not applicable — BuilderAttribution does not approve or reject orders. It observes, tags, logs, and reconciles.

RESHAPE_REQUIRED

Not applicable — BuilderAttribution does not reshape orders.

REJECT

Not applicable as a trading decision. BuilderAttribution emits no RiskVote. The only action that resembles a reject is quarantining drift records.

WARNING_ONLY

Missing builder_code on an inbound order triggers an alert but does not block the order — BuilderAttribution attaches the code and flags the anomaly. Reconciliation drift triggers quarantine and alert but does not halt trading.

13. Standard Decision Output

This bot returns a GovernanceLog object. See GovernanceLog schema.

{
  "attribution_id": "gov.builder_attribution",
  "event_type": "RECONCILIATION_COMPLETE",
  "window_start": "2026-05-08T00:00:00Z",
  "window_end": "2026-05-09T00:00:00Z",
  "local_volume_usd": 48320.5,
  "polymarket_volume_usd": 48320.5,
  "local_order_count": 217,
  "polymarket_order_count": 217,
  "drift_detected": false,
  "quarantine_count": 0,
  "builder_code": "polytraders",
  "retention_days": 90,
  "reconciled_at": "2026-05-09T00:05:12Z"
}

14. Reason Codes

CodeSeverityMeaningActionUser-facing message
BUILDER_CODE_MISSINGWARNAn outgoing order arrived at the attribution layer without the builderCode bytes32 field set, or a fill confirmation echoed back a zero builder code.Attach the configured builderCode and emit WARN alert.An order was detected without the required tracking code. It was added automatically and the anomaly was flagged.
BUILDER_FEE_RATE_CAPPEDWARNThe observed builder_fee_bps on a fill exceeds the V2 cap (taker: 100 bps, maker: 50 bps).Log the anomaly; quarantine the fill record for manual review.
RECONCILIATION_DRIFT_OBSERVEDWARNLocal fill volume or count diverges from the Polymarket builder-code report by > 1%.Quarantine drift records; emit reconciliation drift alert.A difference was found between our records and the exchange's report. The affected records have been set aside for review.
PARAMETER_CHANGE_REQUIRES_APPROVALHARD_REJECTreconcile_window_h exceeds the 72h hard maximum, or builder_code was changed without a signed admin action.Reject the config change and emit an alert.
BUILDER_ATTRIBUTION_CODE_MISMATCHWARNAn order's builder bytes32 field does not match the configured builderCode value.Reject the order from proceeding to signing; emit WARN alert.
BUILDER_ATTRIBUTION_QUARANTINE_BLOCKEDWARNAn automated process attempted to clear quarantine records without a manual review flag.Reject the clear operation; retain records; emit alert.Affected records are held for review and cannot be cleared automatically.
BUILDER_ATTRIBUTION_REPORT_UNAVAILABLEWARNData API builder-code report is unavailable at reconciliation time.Skip this reconciliation cycle; emit alert; retry on next scheduled window.

15. Metrics & Logs

Metrics emitted

MetricTypeUnitLabelsMeaning
polytraders_gov_builderattribution_fills_logged_totalcountercountmarket_idTotal fill events logged to the attribution ledger.
polytraders_gov_builderattribution_volume_pusd_totalcounterusdCumulative pUSD volume attributed to the builder code.
polytraders_gov_builderattribution_drift_usdgaugeusdAbsolute drift between local and Polymarket volume at the last reconciliation.
polytraders_gov_builderattribution_quarantine_countgaugecountNumber of fill records currently in the quarantine partition.
polytraders_gov_builderattribution_missing_code_totalcountercountTotal orders seen without a builder code; should be 0 in normal operation.
polytraders_gov_builderattribution_reconcile_latency_mshistogramsecondsWall-clock latency of a full reconciliation cycle.

Alerts

AlertConditionSeverityRunbook
BuilderAttributionMissingCoderate(polytraders_gov_builderattribution_missing_code_total[5m]) > 0P1#runbook-builderattribution-missing-code
BuilderAttributionDriftDetectedpolytraders_gov_builderattribution_drift_usd > 0P1#runbook-builderattribution-drift
BuilderAttributionQuarantineGrowingdelta(polytraders_gov_builderattribution_quarantine_count[1h]) > 0P2#runbook-builderattribution-quarantine
BuilderAttributionReportUnavailablerate(polytraders_gov_builderattribution_fills_logged_total[30m]) == 0P2#runbook-builderattribution-report

Dashboards

  • Grafana — Governance / BuilderAttribution reconciliation
  • Grafana — Fee accounting / builder code volume and drift

Log levels

LevelWhat gets logged
DEBUGPer-fill record details including builder_fee_bps and fill_confirmed_at.
INFOFill logged; reconciliation cycle completed (pass or drift).
WARNMissing builder code on order; reconciliation drift detected; quarantine records added.
ERRORData API report unavailable at reconciliation time; Postgres write failure.

16. Developer Reporting

{
  "attribution_id": "gov.builder_attribution",
  "event_type": "FILL_LOGGED",
  "order_id": "ord_00123",
  "market_id": "CLOB:0xabc123",
  "side": "BUY",
  "size_usd": 250.0,
  "price": 0.62,
  "builder_code_present": true,
  "builder_code_echoed": "polytraders",
  "log_sequence_number": 4821,
  "fill_confirmed_at": "2026-05-09T11:45:00Z"
}

17. Plain-English Reporting

SituationUser-facing explanation
Daily reconciliation completed with no discrepanciesThe system checked today's trading records against the exchange's report. All orders, volumes, and attribution codes matched exactly.
Reconciliation flagged a discrepancyA difference was found between our records and the exchange's report. The affected records have been set aside for review. No trading is interrupted, but the discrepancy needs to be resolved.
Order arrived without attribution codeAn order was detected without the required tracking code. The code was added automatically and the anomaly was flagged for investigation.
Historical attribution records requestedAttribution logs are retained for at least 90 days. Older records and any records held in the review queue are retained indefinitely until cleared.

18. Failure-Mode Block

main_failure_modeA fill is processed and attributed but the Polymarket report is unavailable at reconciliation time, causing the local log to be marked as unverified until the next successful fetch.
false_positive_riskQuarantining records due to a temporary data format change in the Polymarket report, when the underlying volume is correctly attributed but the comparison field changed.
false_negative_riskMissing a genuine drift because the reconciliation time window does not fully overlap with the Polymarket report window, leaving a gap that does not appear in either comparison.
safe_fallbackIf the Polymarket builder-code report is unavailable at reconciliation time, skip the comparison for that cycle, emit an alert, and retry at the next scheduled window. Never clear quarantine records automatically — require manual review.
required_dependenciesCLOB fill confirmation stream, Data API Polymarket builder-code report, StrategyRegistry outgoing order stream, Governance audit log storage (90-day retention)

19. Failure-Injection Recipes

ScenarioHow to injectExpected behaviourRecovery
MISSING_BUILDER_CODESubmit order with order.builder = ZERO_BYTES32BuilderAttribution attaches configured builderCode; BUILDER_CODE_MISSING alert emittedAutomatic; code is attached.
DATA_API_REPORT_UNAVAILABLEBlock TCP to data-api.polymarket.com during reconciliation windowReconciliation cycle skipped; BUILDER_ATTRIBUTION_REPORT_UNAVAILABLE alert; records retainedNext cycle reconciles full backlog once Data API is reachable.
RECONCILIATION_DRIFTManually insert an extra fill record into attribution_log with size_pusd=10000RECONCILIATION_DRIFT_OBSERVED alert; drift records quarantinedManual review and removal of synthetic record; reconciliation passes on next cycle.
QUARANTINE_AUTO_CLEAR_BLOCKEDCall postgres.DELETE on quarantine records without setting manual_review_flag=trueDelete rejected by application guard; BUILDER_ATTRIBUTION_QUARANTINE_BLOCKED alertManual review must be completed before clearing.
BUILDER_CODE_MISMATCHSet order.builder to a different bytes32 valueBUILDER_CODE_MISMATCH alert; PARAMETER_CHANGE_REQUIRES_APPROVAL raised; order blocked from signingCorrect builder code must be set.

20. State & Persistence

Maintains a durable Postgres attribution ledger with all fill records, plus a quarantine partition for drift records. Reconciliation state is persisted per window.

State stores

NameKindKeyValue shapeTTLDurability
attribution_logpostgresfill_id{ fill_id, order_id, market_id, side, size_pusd, price, builder_code, builder_fee_pusd, fill_confirmed_at, quarantined: bool, log_seq: int }nonestrong
reconciliation_statepostgreswindow_start + window_end{ local_volume, polymarket_volume, drift_usd, drift_pct, status, reconciled_at }nonestrong

Cold-start recovery

On cold start, Postgres attribution_log is read immediately. No in-memory state needs rebuilding.

On restart

All state is in Postgres and available immediately. The next fill event triggers a fresh log write.

21. Concurrency & Idempotency

AspectSpecification
Execution modelsingle-threaded event loop (fill hook) + scheduled reconciliation goroutine
Max in-flight500
Idempotency keyfill_id
Replay-safeTrue
Deduplicationby fill_id — duplicate fill events are ignored
Ordering guaranteeslog_seq is monotonically increasing per postgres.nextval()
Per-call timeout (ms)500
Backpressure strategyshed
Locking / mutual exclusionnone (Postgres serializable isolation)

22. Dependencies

Depends on (must run first)

BotWhyContract
exec.smart_routerSmartRouter populates the builderCode bytes32 field on each order before BuilderAttribution sees it.order.builder must equal config.builder_code_bytes32 before signing.

Sibling bots (same OrderIntent)

BotWhyContract
sec.contract_address_guardContractAddressGuard logs every security check to BuilderAttribution's governance audit trail.GovernanceLog entry emitted for each SecurityCheck decision.

Used by (auto-aggregated)

6.14 6.3

External services

ServiceEndpointSLA assumedOn failure
Data API (builder-code report)https://data-api.polymarket.com99.9% / 500ms p99Skip reconciliation cycle; emit alert; retry on next window.
CLOB Auth API (fills)https://clob.polymarket.com99.95% / 200ms p99Fill log entry deferred until fill confirmation is received.

23. Security Surfaces

BuilderAttribution reads fill data and writes to the governance ledger. It never signs orders or holds private keys.

Signing surface

This bot does NOT sign anything.

Abuse vectors considered

  • Clearing quarantine records automatically without manual review to hide attribution drift
  • Substituting a different builder code bytes32 on orders to redirect fee attribution
  • Modifying builder_code parameter without a signed admin action

Mitigations

  • quarantine_on_drift is locked immutable; auto-clear is rejected
  • builder_code parameter requires signed admin action and is audit-logged
  • Each fill record is immutable once written; log_seq is monotonically increasing
  • alert_on_missing_code is locked immutable; every missing code alert is raised regardless

24. Polymarket V2 Compatibility

AspectValue
CLOB versionv2
Collateral assetpUSD
EIP-712 Exchange domain version2
Aware of builderCode fieldyes
Aware of negative-risk marketsno
Multi-chain readyno
SDK used@polymarket/clob-client-v2 ^2.x
Settlement contractCTFExchangeV2 on Polygon
NotesV2 builder attribution uses a native builderCode bytes32 field on every order (replaced V1 HMAC-based builder). Both maker and taker orders can carry different builder codes in V2. Builder fee formula: builder_fee = notional * bps / 10000. Taker max 100 bps, maker max 50 bps, 1 bp granularity. Fee is taker-only currently; fill records include builder_fee_pusd for auditability.

API surfaces declared

data_apiclob_auth

Networks supported

polygon

25. Versioning & Migration

FieldValue
spec2.0.0
implementation2.1.3
schema2
released2026-04-28

Migration history

DateFromToReasonAction taken
2026-04-28v1 (USDC.e + HMAC builder)v2 (pUSD + builderCode field)Polymarket V2 cutoverReplaced HMAC builder logic with on-order builderCode bytes32 field. Attribution log schema updated to include builder_fee_bps and builder_fee_pusd columns. Reconciliation report format updated to match Data API V2 builder-code report schema. All fill amounts now denominated in pUSD.

26. Acceptance Tests

Unit Tests

TestSetupExpected result
Attach builder_code when absent on outgoing orderorder.builder_code=undefined, builder_code='polytraders'order.builder_code='polytraders' attached; MISSING_CODE alert emitted
Log fill record with all metadata after fill confirmationFill event: order_id=ord_001, size_usd=300, price=0.55, side=BUYFill record in attribution log with correct fields and log_sequence_number
Reconciliation passes when local and report totals matchlocal_volume=5000, polymarket_volume=5000, local_count=20, report_count=20GovernanceLog event_type=RECONCILIATION_COMPLETE, drift_detected=false
Quarantine records when drift detectedlocal_volume=5100, polymarket_volume=5000 (drift=100)Drift records moved to quarantine, quarantine_count > 0, alert emitted
Reject reconcile_window_h above hard maximumreconcile_window_h=80, hard=72ConfigError PARAMETER_CHANGE_REQUIRES_APPROVAL
Retain quarantine records when auto-clear attemptedAutomated process attempts to clear quarantine without manual review flagQuarantine records remain; alert emitted

Integration Tests

TestExpected result
End-to-end: order tagged, filled, logged, and reconciled against Polymarket reportFull attribution lifecycle completes with matching GovernanceLog entry
Polymarket report unavailability causes skip-and-retry without data lossReconciliation cycle skipped, alert emitted, records retained; next cycle reconciles full backlog
Missing builder_code on 5 consecutive orders triggers escalated alertIndividual MISSING_CODE alerts plus an escalated pattern alert after 5 consecutive missing codes

Property Tests

PropertyRequired behaviour
Every fill event is logged before any downstream report uses itAlways true — fill logging is synchronous with fill confirmation
Quarantine records are never automatically cleared without a manual review flagAlways true
All attribution log records are retained for at least 90 daysAlways true — retention enforcement is mandatory

27. Operational Runbook

BuilderAttribution incidents involve missing builder codes, reconciliation drift, or quarantine growth. Every RECONCILIATION_DRIFT event is a P1 requiring investigation before the next daily report.

On-call actions

AlertFirst stepDiagnosisMitigationEscalate to
BuilderAttributionMissingCodeIdentify which strategy or SmartRouter instance is emitting orders without builderCode.If a single strategy is the source, it may be using an old SDK version that does not set builder bytes32.Pause the affected strategy and require SDK upgrade. BuilderAttribution will attach the code in the interim, but the root cause must be fixed.Governance pod lead + Exec pod lead immediately.
BuilderAttributionDriftDetectedReview reconciliation drift details in the GovernanceLog.Check whether the drift corresponds to a Data API report format change or a genuine attribution discrepancy.Do NOT clear quarantine records until the root cause is confirmed. Engage Polymarket support if drift is large.Governance pod lead immediately.
BuilderAttributionQuarantineGrowingCheck how many records are in quarantine and when they were added.If quarantine is growing steadily, drift may be systematic (e.g., a fill reporting format change).Investigate the fill data format. Do not reduce the drift detection threshold.Governance pod lead after 30 minutes.

Manual overrides

  • polytraders gov clear-quarantine --fill-ids <ids> --reviewed-by <operator> — Clears specific quarantine records after manual review. Requires governance pod lead sign-off and is audit-logged.
  • polytraders gov rerun-reconciliation --window-start <ts> --window-end <ts> — Re-runs a specific reconciliation window without clearing existing records. Used to check if drift resolves after a Data API format fix.

Healthcheck

GET /health → 200 if Postgres attribution_log is reachable, last fill was logged < 300s ago during active trading, and quarantine_count has not increased in the last 24h.

28. Promotion Gates

A bot does not advance to the next readiness state until every gate below is green. Gates are observable from production data — no subjective sign-off.

Promote to Shadow

GateHow measuredThreshold
Unit tests pass for fill logging, builder code attach, and reconciliation logicCI test run100% pass
Postgres write integration test verifiedIntegration testPass

Promote to Limited live

GateHow measuredThreshold
Reconciliation cycle completes within 30s for a 24h window of 1000 fill recordspolytraders_gov_builderattribution_reconcile_latency_ms histogram< 30s
Missing-code alert fires within 1s of order without builderCodeUnit test + integration testPass

Promote to General live

GateHow measuredThreshold
End-to-end: fill tagged, logged, reconciled, GovernanceLog entry matches Data API reportE2E test in stagingPass
Quarantine auto-clear rejection verifiedFailure injection testPass

29. Developer Checklist

Ready-to-ship score: 27/27 sections complete · 100%

RequirementStatus
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