As of 30 Oct 2026, Polygon has 12 audit reports by 6 security firms on Trustblock; the latest is by ChainSecurity, dated 8 May 2025. Those reports list no open critical findings. It also holds 2 deployed contracts on 1 chain.
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 |
|---|---|---|---|---|---|
| Vault Bridge Token | Security firm: ChainSecurity | Date: | Scope: Files named in the report | No open critical findings | Open · chainsecurity.com |
| POL Transition Smart Contracts | Security firm: ChainSecurity | Date: | Scope: Files named in the report | 1 critical finding, fixed | Open · chainsecurity.com |
| Polygon security review | Security firm: Sigma Prime | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · GitHub |
| Polygon Token (POL) Security Audit Audit · firm’s term: security audit | Security firm: ChainSecurity | Date: | Scope: Files named in the report | No open critical findings | Open · chainsecurity.com |
| Polygonid security review | Security firm: Nethermind Security | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · GitHub |
| Polygon security review | Security firm: Sigma Prime | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · GitHub |
| Polygon Technology security review | Security firm: Hexens | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · GitHub |
| Polygon PoS Portal | Security firm: ChainSecurity | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · chainsecurity.com |
| Polygon ZkEVM security review | Security firm: Hexens | Date: | Scope: Not recorded (see the report) | 4 critical findings, fixed | Open · GitHub |
| Polygon Fx Portal | Security firm: ChainSecurity | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · chainsecurity.com |
| Audit Report | Security firm: Paladin | Date: | Scope: 2 addresses on Polygon (POS) | No open critical findings | Open · paladinsec.co |
| Matic | Security firm: CertiK | Date: | Scope: Files named in the report | 1 critical finding, fixed | Open · skynet.certik.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 6 |
| High | 0 | 0 | 6 |
| Medium | 1 | 5 | 10 |
| Low | 1 | 9 | 57 |
The report gives no description here.
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 report gives no description here.
Open the reportRootChainManager.sol lines 250-255 the exitHash is determined by three factors, one of which is inputDataRLPList[8], the branch mask, i.e. the path in the receipt merkle patricia trie from the root to the corresponding burning transaction receipt. The path is in bytes and translated to hex by _getNibbleArray() in MerklePatriciaProof.sol. There are 2 cases depending whether the path in hex has odd or even length. In case on line 150 we accept every beginning nibble except 1,3 and erase the first two nibble in the hex array, which means two arrays 2055 and 4055 would produce the same _getNibbleArray() to bypass `verify`, but they produce different exitHash so one can exit more than once.
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 report gives no description here.
Open the reportThe report gives no description here.
Open the reportMatic wants to enable users to send transactions to matic network without changing the network in their wallet so the chainId is the same for both child chain and main chain. This opens an attack vector when a user wants to send a transaction only to the child chain, then the attacker can submit the signed transaction to the other chain against that user’s will. The requires the same nonce, which can happen, and the same contract address on both chains to have an exploitable function, for example when the two contracts are deployed from the same address.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 report gives no description here.
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 function `numItems()` calculates the number of elements in an `RLPItem` representing a list, so it should check whether the input indeed represents a list. For example it would return the length of a string. On the other hand adding a `require` check is not necessary and would only cost more gas, since the only place this function is used is in `toList()` and the aforementioned condition is already checked. The exhibit is here just for completeness in case the `RLPReader.sol` library is expanded and the function `numItems()` is used in additional functions.
Open the report`require` can be used to check for conditions and throw an exception if the condition is not met, in which case the error message provided by the developer will appear. This is why a very descriptive error message is needed.
Open the reportIn the constructors of `ChildToken` contracts the depositor role is assigned to the contract’s creator. The depositor is an important role as it is the only address that is authorized to deposit the tokens from root contract to child contract. From the natspec it is evident that only the `ChildChainManager` contract should possess this role and this contract does not deploy the `ChildToken` contracts so one would needs some transactions to pass over the depositor rights.
Open the reportIn several functions of `RLPReader` library we check that `item.len` is not zero. Indeed any RLP encoding (even of empty string or empty array) is non-empty, this means we should check this condition in the function `toRlpItem()` to exclude this case before hand.
Open the reportAccording to RLP encoding specification the special value “false” is encoded as “0x80”, whereas in current implementation of the function “toBoolean” it is “0x00”.
Open the reportThe subtraction `blockNumber - startBlock` is unsafe and can cause integer underflow, but we believe this cannot be exploited in any way as it would certainly cause the Merkle proof verification to fail.
Open the reportThe IChildToken interface contains only the deposit function and is inherited in every Child Token contract. Every Child Token contains an additional withdraw function which is essential because it enables token withdrawal from the child chain to the main chain so we believe this function belongs to the general pattern as well, i.e. IChildToken interface.
Open the reportThe value in storage `childToRootToken[childToken]` is looked up twice in exit function. Each lookup costs 200 gas each. It would be better to assign this value to a memory variable, because both memory assignment and look up cost 3 gas each.
Open the reportThe functions `toUint()` and `toUintStrict()` only take `RLPItem` representing uint as input. To get the data bytes only the length of the payload offset is calculated, whereas the content of this prefix is not considered, which means invalid `RLPItem` with prefixes of incorrect length or short list would still get through.
Open the reportThe default return value is false so the return statements on lines 107 and 102 are not needed and the else case on line 101 can be omitted.
Open the reportAn unlocked compiler version in the source code of the contract permits the user to compile it at or above a particular version. This, in turn, leads to differences in the generated bytecode between compilations due to differing compiler version numbers. This can lead to an ambiguity when debugging as compiler specific bugs may occur in the codebase that would be hard to identify over a span of multiple compiler versions rather than a specific one.
Open the reportChecking in the function `numItems()` whether `item.len == 0` to return zero is not needed since if `item.len == 0` then it does not encode a list, because the RLP encoding of an empty list is `0xC0`. Moreover the function `numItems()` is only used in `toList()` and right before calling `numItems()` the condition `isList()` is checked which excludes the possibility of an empty item.
Open the report| Address | Chain | Source code |
|---|---|---|
| 0xa9de…e4920xa9de045d9e8b619ed12fc4947f10d371621de492 | Chain: Polygon (POS) | Source code: Verified source |
| 0xd9d2…31a30xd9d2114c8ea72298d5748f9684b4aadfec6731a3 | Chain: Polygon (POS) | Source code: Verified source |
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="polygon"></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