As of 30 Oct 2026, Polymarket has 7 audit reports by 2 security firms on Trustblock; the latest is by Quantstamp, dated 5 Oct 2026. Those reports list no open critical findings.
Record last updated . It holds audits and findings, contracts and incidents up to Oct 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Polymarket v2 | Security firm: Quantstamp | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · certificate.quantstamp.com |
| Polymarket CTF Exchange v2 | Security firm: Quantstamp | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · certificate.quantstamp.com |
| UMA Sports Oracle | Security firm: ChainSecurity | Date: | Scope: Files named in the report | No open critical findings | Open · chainsecurity.com |
| NegRiskAdapter | Security firm: ChainSecurity | Date: | Scope: Files named in the report | No open critical findings | Open · chainsecurity.com |
| Conditional Tokens | Security firm: ChainSecurity | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · chainsecurity.com |
| Proxy Wallet Factories | Security firm: ChainSecurity | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · chainsecurity.com |
| Exchange | Security firm: ChainSecurity | Date: | Scope: Not recorded (see the report) | 2 critical findings, fixed | Open · chainsecurity.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 2 |
| High | 0 | 0 | 2 |
| Medium | 0 | 0 | 8 |
| Low | 1 | 8 | 22 |
When the OOv2 refunds on dispute to the `OptimisticOracleModule` and the direct ERC20 transfer reverts (for example the module address is blacklisted or the token is paused), `OptimisticOracleV2._transferOrDeferPayout()` falls back to recording the amount in `deferredPayouts[currency][module]` and emits `PayoutDeferred`. The only way to move those funds out is a call to `OOV2.claimDeferredPayout(currency, repaymentAddress)`, which requires `msg.sender` to equal the deferred recipient (the module itself). `OptimisticOracleModule` exposes no function that forwards a `claimDeferredPayout()` call to the OOv2, once a deferred payout is recorded against it, the funds remain trapped in the OOv2. Under normal operation with standard bond tokens the transfer to the module is expected to succeed, so the defer path is unlikely to be triggered.
Open the report`validateOrder()` only validates order level state and signature data. It does not take execution specific context such as `fillAmount`, `fee`, `conditionId`, or maker side orders, so it cannot mirror the checks performed during `matchOrders()`. As a result, an order can pass `validateOrder()` but still revert during execution due to remaining capacity, fee bounds, token ID alignment, or other match specific checks.
Open the reportThe documentation contains stale information compared to the actual audited implementation, likely because the code changed shortly before the audit happened without updating the docs. The verified misalignments are: 1. `src/oracle/modules/README.md` states that `onArbitrationTriggered()` reverts with `ArbitrationNotExpected` as a safety check. `OptimisticOracleModule` does not implement `onArbitrationTriggered()` and does not define `ArbitrationNotExpected`. If `OracleAggregator.disputeResult()` reaches arbitration for a request configured with `OptimisticOracleModule` as the arbitrator, the call is made through `IArbitratorModule(cfg.arbitratorModule).onArbitrationTriggered(...)`. Because the function is not implemented and there is no fallback handler, the call reverts with a generic error instead of the documented custom error. 2. `docs/position-ids.md` and `docs/position-manager.md` document `PositionManager.getPositionId(conditionId, outcomeIndex)`, but that function does not exist in `PositionManager`. 3. `docs/position-ids.md` references router callback helpers that do not exist in `Router`. 4. `docs/architecture.md` and `docs/position-manager.md` use stale PMCT and `collateralToken` naming instead of current `pUSD` and `COLLATERAL_TOKEN` naming. 5. `docs/exchange.md` documents stale order fields, EIP712 domain values, initializer, constructor, fee controls, pause controls, `matchOrders` argument order, and view names. 6. `docs/modules.md` describes an old oracle assignment model. Current modules use resolver and bridge roles. 7. `docs/modules.md` lists stale bridge and OracleModule functions, and an incomplete `convert` signature. 8. `docs/router.md` has stale merge behavior, AutoRedeemer API, and omits BridgeRouter refund forwarding. 9. `docs/oracle.md` has stale auth details, and has the wrong initializer signature. 10. `docs/auth.md` omits resolver role support, overstates `InitializableRoles`, and repeats stale Exchange and AutoRedeemer APIs. 11. `docs/bridge.md` documents module support by module id, stale message types, stale payload helpers, and incorrect duplicate result behavior. 12. `docs/migration.md` documents stale migration argument shapes, stale operator overloads, overbroad revert behavior, and internal helpers as public API.
Open the report`OptimisticOracleModule` creates UMA requests using a request tuple that includes the module address, identifier, timestamp, and ancillary data. When `_reRequest()` is called after a dispute or through `forceRerequest()`, it reuses the same identifier and ancillary data, and relies on `block.timestamp` as the only value that changes the underlying UMA request ID. If two re-requests for the same condition are attempted in the same block with the same ancillary data, the second call attempts to create an already-existing UMA request. The underlying Optimistic Oracle rejects duplicate request IDs, causing the later request to revert. This creates a temporary griefing vector against admin `forceRerequest()` calls. A user can front-run an admin’s `forceRerequest()` by disputing the current price request. The dispute callback triggers `_reRequest()` first, creating a new request with the existing ancillary data and current block timestamp. If the admin transaction then executes in the same block with the same ancillary data, it reverts before applying the admin-selected bond token, bond amount, liveness, or zero-reward reset. The impact is temporary liveness degradation rather than permanent request blocking. The admin can retry in a later block, or use different ancillary data, but the failed force action may delay recovery and leave the condition on the automatically created re-request using the prior request parameters.
Open the reportThe contracts currently use a mixture of access control abstractions, including `Auth`, `Roles`, `InitializeableRoles`, and direct inheritance from Solady’s `OwnableRoles`. This inconsistency makes it harder to determine which roles exist on each contract, what permissions they grant, and which administrative functions are actually relevant. In some cases, contracts expose role management functions for roles that are not used by that contract, increasing the administrative surface area without a corresponding need.
Open the reportThe report gives no description here.
Open the reportThe report gives no description here.
Open the reportThe report gives no description here.
Open the reportThe reports name a repository or files. Open a report to see its scope.
Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.
Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="polymarket"></div></body>
Paste the code where the label should appear. It uses no API credit and updates by itself.
Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us