QUICK ANSWER
We ran our scanner on 23 small Solidity contracts that each contain one known bug, most modeled on real exploits like The DAO (2016) and Parity (2017). It flagged 23 of 23. On 18 patched or correctly written contracts it raised no high or critical finding, and on 16 audited OpenZeppelin contracts it reported nothing at all.
| Contract | Bug class | Modeled on | Result |
|---|---|---|---|
| dao reentrancy | Reentrancy | The DAO (2016) | criticalReentrancy: credit updated after external call in withdraw() |
| bank reentrancy | Reentrancy | SWC-107 | criticalReentrancy: balances updated after external call in withdrawAll() |
| poly access control | Access control | Poly Network (2021) | criticalMissing access control: anyone can change keeper via putCurEpochConPubKeyBytes() |
| unprotected owner | Access control | Ethernaut: Fallout | criticalMissing access control: anyone can change owner via setOwner() |
| unprotected mint | Access control | SWC-105 | criticalMissing access control: unrestricted mint in mint() |
| cream spot oracle | Spot price oracle | Cream Finance (2021) | highManipulable spot price oracle in getPrice() |
| tx origin wallet | tx.origin authorization | SWC-115 | hightx.origin used for authorization in transferTo() |
| unchecked send | Unchecked send / call | SWC-104 | highUnchecked return value of .send() in sendToWinner() |
| overflow legacy | Integer overflow (pre-0.8) | SWC-101 / BeautyChain (2018) | highInteger overflow/underflow: Solidity ^0.6.0 without SafeMath |
| delegatecall proxy | Delegatecall | SWC-112 / Parity | criticalDelegatecall to caller-supplied address in forward() |
| timestamp game | Timestamp-based outcome | SWC-116 | highPredictable randomness from block.timestamp (timestamp-dependent outcome) in receive() |
| weak randomness | Predictable randomness | SWC-120 / Ethernaut: Coin Flip | highPredictable randomness from block.timestamp (timestamp-dependent outcome) in pickWinner() |
| unprotected selfdestruct | Unprotected selfdestruct | SWC-106 / Parity (2017) | criticalUnprotected selfdestruct in kill() |
| unbounded loop dos | Denial of service | SWC-128 | highDenial of service: unbounded loop with payments in distribute() |
| king dos | Denial of service | Ethernaut: King | highDenial of service: refund to king can block receive() |
| signature replay | Signature replay | SWC-121 | highSignature replay: claim() accepts the same signature repeatedly |
| unprotected initializer | Unprotected initializer | Wormhole / Nomad-style upgrade bugs | criticalUnprotected initializer: initialize() can be called by anyone, any time |
| reentrancy cross function | Reentrancy | SWC-107 (cross-function) | criticalReentrancy: stakes updated after external call in unstake() |
| oracle balance price | Spot price oracle | Harvest / bZx-style balance oracles | highManipulable spot price oracle in sharePrice() |
| tx origin ownership | tx.origin authorization | Ethernaut: Telephone | hightx.origin used for authorization in changeOwner() |
| reentrancy delete after call | Reentrancy | SWC-107 variant | criticalReentrancy: deposits updated after external call in refund() |
| unprotected oracle setter | Access control | Unprotected price feed setter | criticalMissing access control: anyone can change priceFeed via setPriceFeed() |
| unchecked payable send | Unchecked send / call | SWC-104 variant | highUnchecked return value of .send() in split() |
Patched twins of the bugs above plus common correct patterns that crude scanners misfire on: OpenZeppelin initializers, nonce-protected signatures, pull payments, SafeMath on Solidity 0.7, Chainlink price feeds, two-step ownership and proxies.
| Contract | Pattern | Result |
|---|---|---|
| dao reentrancy fixed | Reentrancy | No high/critical alarm |
| owner fixed | Access control | No high/critical alarm |
| wallet msg sender | tx.origin authorization | No high/critical alarm |
| checked call | Unchecked send / call | No high/critical alarm |
| simple token | Integer overflow (pre-0.8) | No high/critical alarm |
| init guarded flag | Unprotected initializer | No high/critical alarm |
| init oz modifier | Unprotected initializer | No high/critical alarm |
| signature with nonce | Signature replay | No high/critical alarm |
| king pull payment | Denial of service | No high/critical alarm |
| batch airdrop calldata | Denial of service | No high/critical alarm |
| safemath legacy | Integer overflow (pre-0.8) | No high/critical alarm |
| chainlink oracle | Spot price oracle | No high/critical alarm |
| guarded selfdestruct | Unprotected selfdestruct | No high/critical alarm |
| timelock deadline | Timestamp-based outcome | No high/critical alarm |
| paid nft mint | Access control | No high/critical alarm |
| two step ownership | Access control | No high/critical alarm |
| guarded reentrancy | Reentrancy | No high/critical alarm |
| minimal proxy | Delegatecall | No high/critical alarm |
A contract only counts as detected if the scanner reports a critical or high finding in the same bug class as the planted bug. An unrelated warning doesn't count.
A safe contract fails if it gets any high or critical finding, in any class. That's stricter than counting only same-class mistakes, because noise is noise.
These are small, single-bug contracts, so this measures whether each detector works, not how the scanner handles a 3,000-line protocol. Treat any scanner as a first pass before a manual audit.
Last run 2026-10-04. Engine: Pattern engine (same for free and Pro; Pro adds Claude AI analysis on top).
This is our benchmark. If you find a vulnerable contract it misses, or a safe one it flags, send it in. Confirmed finds get fixed and credited.
On our public benchmark it detected 23 of 23 known-vulnerable contracts and raised no high or critical finding on 18 safe contracts. It also reported nothing on 16 audited OpenZeppelin v4 and v5 contracts.
The scanner has to report a critical or high finding in the same bug class as the planted bug. A serious finding about something unrelated doesn't count, so noise can't inflate the score.
No. These are small contracts with one bug each, and real code is harder. Use the scanner as a first pass to catch the well-known bug classes before you pay for a manual audit, not instead of one.
No. Free and Pro run the same 13 pattern detectors, so these results apply to both. Pro adds an AI review on top, plus PDF reports and full scan history.
Written by Duron Epps, Founder ยท Last updated October 2026