Solidity static analysis tools: what they catch, and what they miss

static analysis
Table of Contents

A spell checker will catch recieve every time. It will never tell you that the paragraph argues the opposite of what you meant. Both are errors. Only one of them has a rule.

That is the whole story of static analysis on Solidity, and it is why teams who run a clean scan still get drained. Slither, Aderyn, Solhint and Semgrep are free, they run in seconds, and you should have all of them in CI by the end of the week. They are also, by the published measurements, unable to reach the class of bug that takes most of the money.

Quick answer

Solidity static analysis tools read your contract without running it and flag patterns that match a known rule. The best of them are free, open source and fast enough to run on every commit. In a study of 127 high-impact attacks costing $2.3 billion, five leading automated tools could have prevented 8% of them, and every one of those was reentrancy. The gap is business logic, economics and intent, none of which has a general rule.

What static analysis actually does

Static analysis reads source code, or compiled bytecode, without executing it. A Solidity analyser parses your contracts into an abstract syntax tree and a control-flow graph, then walks that structure asking a fixed set of questions. Is state written after an external call? Is a return value ignored? Can this function be called by anyone?

Two properties follow, and both matter more than any feature list.

It is deterministic. The same code and the same version of the tool produce the same findings every time, which is what makes a scan a sane thing to gate a pull request on.

It is bounded by its rules. A detector exists or it does not. There is no partial credit and no intuition, so a tool’s coverage is exactly the list of questions somebody thought to encode.

The tools worth knowing, and what each one is

Licences and release dates read from each project’s repository on 2 September 2026. They go stale, so check them.

Tool What it is Licence Latest release
Slither “A Solidity & Vyper static analysis framework written in Python3”, from Trail of Bits. 100 detectors, plus printers and an API for custom analyses AGPL-3.0 0.11.6, 28 July 2026
Aderyn “A Rust-based solidity smart contract static analyzer”, from Cyfrin. No configuration on Foundry or Hardhat, outputs Markdown, JSON and SARIF GPL-3.0 v0.6.8, 22 January 2026
Solhint A linter, “both Security and Style Guide validations”, from Protofire. 68 rules, 18 of them security MIT v6.2.4, 13 August 2026
Semgrep A general-purpose pattern matcher, with the community smart contract ruleset at p/smart-contracts. Solidity is Experimental, the least mature tier LGPL-2.1 rolling
Wake “The fuzzing and testing framework for Solidity, written in Python”, from Ackee Blockchain. 26 detectors, a fuzzer and a language server ISC v5.0.0rc2, 12 April 2026
Olympix Commercial and closed source, built around an IDE extension and its own compiler. Its detection claims are vendor-published with no independent benchmark proprietary not public

Four more names appear on almost every list of Solidity static analysis tools, and none of them is static analysis. The label decides what you can reasonably expect each one to tell you.

Tool What it really is The catch
Mythril “A symbolic-execution-based security analysis tool for EVM bytecode”. It reasons about paths with a solver, on compiled bytecode rather than your source Deeper on the paths it explores, much slower, and it does not explore all of them. Last tagged release v0.24.8, March 2024
Echidna A fuzzer. “A Haskell program designed for fuzzing/property-based testing of Ethereum smart contracts” No properties, no findings
Foundry A test framework with fuzzing and invariant testing built in. Fuzz tests default to 256 runs, invariant runs to 256 runs at depth 100 Same as Echidna. The value is entirely in the properties you thought to assert
Certora Prover Formal verification. It takes bytecode plus a CVL specification, turns both into a mathematical formula and hands it to SMT solvers It proves rather than samples, but only within the spec you wrote. Source is GPL-3.0, a personal access key is free

What they genuinely catch, and it is not nothing

Static analysers are very good at the vulnerability classes that have a shape.

  • Reentrancy in its common forms, the class with the strongest tool support anywhere in this field.
  • Unchecked return values, unsafe delegatecall, tx.origin used for authentication, unprotected selfdestruct, uninitialised storage and state-variable shadowing.
  • Reliance on block.timestamp or blockhash where it can be influenced.
  • Unprotected initialisers and upgradeable-proxy mistakes, which Slither has dedicated tooling for.
  • Code-quality and gas issues that are not vulnerabilities but do make review cheaper.

They are also fast in a way no other layer is. Slither’s documentation claims under a second per contract, and an independent evaluation across 47,518 Ethereum contracts measured it at roughly five seconds, the fastest of the nine tools tested.

The fairest published verdict comes from a paper that is otherwise hard on tooling. In the ICSE 2024 study of real-world attacks, “Slither detects the most vulnerabilities, but it also reports many false positives”, and of the eleven exploited vulnerabilities that any tool caught, ten could only be detected by Slither. Both halves of that sentence are true, and the first half is a strong result for one free tool.

False positives, and the operational cost nobody budgets for

The same speed that makes these tools cheap to run makes them cheap to ignore.

The 2020 evaluation of nine tools across the whole of Etherscan’s verified Solidity found that 97% of contracts were tagged as vulnerable, which the authors read as “a considerable number of false positives”. A survey quoted in the 2024 paper looked at 23,000 contracts that academic papers had reported as vulnerable and found only 1.98% had been exploited since deployment.

Slither’s own detector list says the same thing more precisely. Of its 100 detectors, 29 are High impact and 21 are Informational, and 41 of the 100 carry Medium confidence rather than High. Those are honest labels, published by the tool’s authors, and they describe something built to raise questions rather than hand you a verdict.

The cost is not the false finding. It is what a team does after the fiftieth one. Engineers learn to skim the report, a suppression is added because the finding looked like the last four, and the one that mattered goes past on a Thursday afternoon. We have written separately on why access control findings are the hardest of all to judge from syntax alone.

Two habits beat any tool choice here. Run the scan on every pull request, so the diff of findings is small enough to read. And give every suppression a written reason, because an unexplained suppression is indistinguishable from a missed bug six months later.

What they miss, and this is the part that costs money

Three independent studies, in three different years, arrive at the same place from different directions.

Study Method The finding
Chaliasos et al., ICSE 2024 5 tools against 127 high-impact attacks worth $2.3 billion, plus 49 practitioners surveyed The tools “could have prevented a mere 8% of the attacks”, $149 million of $2.3 billion. “All preventable attacks were related to reentrancy”
Zhang et al., ICSE 2023 516 exploitable bugs from 167 real contracts, 2021 to 2022, mostly from Code4rena “More than 80% exploitable bugs are beyond existing tools”, which the authors call machine unauditable bugs
Durieux et al., ICSE 2020 9 tools, 69 annotated contracts, 47,518 live contracts All nine tools combined detected 42% of the annotated vulnerabilities. The best single tool managed 27%

The 2024 paper is the most direct about why. The two commonest categories in its attack dataset were absence of coding logic or sanity checks and on-chain oracle manipulation, and neither can be detected by current automated tools. The 2023 paper sorts the same gap into seven root causes: price oracle manipulation, erroneous accounting, ID uniqueness violations, inconsistent state updates, privilege escalation, atomicity violations, and bugs specific to one implementation. Read as a list of what a rule cannot describe, they collapse into five things.

What is missed Why no detector reaches it What it looks like
Business logic and accounting The tool has no idea what your contract is supposed to do, and arithmetic that computes the wrong quantity has no syntactic tell Fees taken twice, rounding that always favours one side, a balance updated in one path and not another
Economic and incentive design Economic soundness is a property of a market, not of a function. Nothing in the syntax tree expresses “profitable to attack” Liquidation thresholds that pay an attacker to cause the liquidation, emissions that can be recursively farmed
Cross-contract and cross-protocol interaction Analysis is scoped to the code you point it at. The dangerous behaviour is in the composition A donation that moves a vault’s share price, a callback in an integrated token, a flash loan that makes an assumption briefly false
Governance and access-control intent A tool sees that a function is guarded. It cannot see whether the guard is the right one, or who ultimately controls it A timelock a single multisig can bypass, a role granted at deploy and never revoked, an undocumented upgrade path
Oracle assumptions Whether a price feed can be moved is a question about the market behind it, not about the call site Spot price read from a pool an attacker can push, no staleness check, a fallback that silently returns zero

Here is the difference, in one contract. The bug in the first function is caught by every tool above. The bug in the second is caught by none of them.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract RewardPool {
    mapping(address => uint256) public shares;
    uint256 public totalShares;

    function deposit() external payable {
        shares[msg.sender] += msg.value;
        totalShares += msg.value;
    }

    // Every analyser in this article flags this. The external call happens
    // before the state is cleared, which is the reentrancy pattern, and it
    // has had a detector in every tool for years.
    function claimReentrant() external {
        uint256 userShares = shares[msg.sender];
        uint256 payout = (address(this).balance * userShares) / totalShares;
        (bool ok, ) = msg.sender.call{value: payout}("");
        require(ok, "transfer failed");
        shares[msg.sender] = 0;
        totalShares -= userShares;
    }

    // No detector flags the bug. A linter may note the low-level call, as it
    // does above, but that is not the problem here. Effects come before the
    // interaction, the arithmetic is checked, access control is not the
    // question, and no rule describes the property that breaks: totalShares is
    // never decremented, so every later claimant is paid a smaller fraction
    // than they own and the remainder is stranded in the contract permanently.
    function claim() external {
        uint256 userShares = shares[msg.sender];
        uint256 payout = (address(this).balance * userShares) / totalShares;
        shares[msg.sender] = 0;
        (bool ok, ) = msg.sender.call{value: payout}("");
        require(ok, "transfer failed");
    }
}

The second function is a one-line omission with a permanent cost, and there is nothing wrong with it that a pattern can name. The property it breaks, that the sum of every account’s shares always equals totalShares, is obvious to a person and invisible to a rule. That property has a name. It is an invariant, and stating it is what moves the bug into reach of a fuzzer, a prover or a reviewer.

Why a clean Slither run is not a security guarantee

Worth saying plainly, because the report looks so much like a certificate.

A clean run means no rule matched. It does not mean no rule was needed. The 2023 study ran Slither and Oyente over its dataset and neither detected a single bug it had classified as beyond tooling, which is the expected result rather than a failure.

Coverage is the union of what somebody encoded. The 2020 evaluation found two whole vulnerability categories that none of the nine tools could detect by design.

And it was true on one commit. Merge a branch and the statement expires, which is the same reason a point-in-time audit decays.

The 2023 authors add the sentence that keeps all of this honest: their finding “does not suggest existing tools are ineffective”, because many of the bugs those tools do catch were caught during development and never reached a dataset. The tools work. They work on a defined slice.

Static analysis, symbolic execution, fuzzing and formal verification

Four techniques get bundled together as “automated security tooling” and they answer four different questions. Dynamic analysis is not a fifth one, it is the umbrella term for anything that runs the code, which here means fuzzing and invariant testing.

Technique What it does What it can prove Cost to adopt
Static analysis Reads code without running it, matches known patterns That a pattern is present. Never that a property holds Minutes. Free
Symbolic execution Explores paths with a solver, reasoning over ranges of inputs at once That a specific reachable state exists, on the paths it managed to explore Hours, and slow runs
Fuzzing and invariant testing Runs the contract thousands of times on generated inputs, checking properties you wrote That your property survived every sequence it tried. Never that no counterexample exists Days of engineering. The properties are the work
Formal verification Compiles code plus a specification into a formula and proves it That the property holds for all inputs, within the spec and where the solver terminates Weeks. Specialist skills

Fuzzing and formal verification are the two that reach into the logic layer, and the ICSE 2024 study puts a number on it: tools capable of detecting logic errors and missing sanity checks, meaning property-based fuzzers, formal verification and model checking, could have prevented 37% of the 127 attacks, against 8% for the scanners. Certora’s own white paper is candid about the ceiling, noting that formal verification is an undecidable problem, that solvers can time out inconclusively, and that “errors in a specification can lead users to incorrectly conclude that their contracts are correctly implemented”.

Our longer treatment of the last two sits in formal analysis in Web3, without the math.

The stack to actually run

In this order, because each layer costs more than the one above it.

Layer What to run Why here
Pre-commit Solhint Cheapest feedback there is, and 18 of its 68 rules are security rules
Every pull request Slither, plus Aderyn Seconds per run. Keep a triaged baseline so what gets read is the diff of findings, not the whole report. Aderyn is a different implementation with a different detector set
Every pull request, optional Semgrep with p/smart-contracts Rules derived from real DeFi exploits. Solidity is Experimental, so treat it as a supplement
Nightly, on contracts holding value Mythril Slower than everything above and reasons differently, so it does not belong on the critical path
Before a release Foundry invariant tests, then Echidna or Wake Where the return stops being free and starts being real, because writing the properties forces you to state what your protocol guarantees
Where one property is worth weeks Formal verification A solvency invariant on a lending market usually is
Before mainnet A person reading it for intent The only layer that reaches the 80%

Where a manual audit fits, precisely

Not as a replacement for any of the above. Every serious auditor runs the same free tools you do, on the first afternoon, for the same reason a surveyor uses a damp meter: it clears the mechanical ground fast so the expensive attention goes where it is needed.

The reason to pay a person is the five things a detector cannot reach. Somebody has to decide whether your accounting is right, whether your incentives can be gamed, what happens when your protocol is composed with one you have never heard of, whether your governance can be short-circuited, and whether your price feed can be moved by whoever calls you.

Fidesium’s manual smart contract audits are line-by-line human review, chain agnostic with an EVM specialism and Solana coverage, covering logic and economic risk, with two rounds of fix verification included. They start at $5,000 and the reports are published: the audit portfolio is the work rather than a summary of it. For scope and price rather than method, that is what security services covers.

Then there is the part everyone underestimates. An audit describes one commit. So does a scan. Both expire the moment somebody merges, which is why Fidesium runs audit-grade analysis continuously, on every commit, pull request and deployment, with the plan prices published rather than quoted on request. An audit does not make a contract safe. It tells you what was true about the code on the day somebody looked, and the only honest way to keep that current is to keep looking.

Frequently asked questions

What are the best Solidity static analysis tools in 2026?

Slither is the default and the most capable, with 100 detectors and detector-writing APIs. Aderyn is a fast Rust analyser that needs no configuration on Foundry or Hardhat projects. Solhint is the linter to run first, with 18 security rules among its 68. Semgrep with the p/smart-contracts ruleset adds patterns derived from real DeFi exploits, though its Solidity support is still Experimental. Wake adds 26 detectors alongside a fuzzer and a language server. All five are free and open source.

Is Mythril a static analysis tool?

No. Mythril is a symbolic-execution tool that works on compiled EVM bytecode, so it reasons about execution paths using a solver rather than matching patterns in your source. It is commonly listed as a static analyser, it is slower than one, and its last tagged release is v0.24.8 from March 2024.

Is fuzzing static analysis?

No. Fuzzing runs the contract. Echidna, Foundry’s forge fuzz and invariant tests, and Wake’s fuzzer all generate inputs and execute the code against properties you have written, so a fuzzer finds nothing until you have stated what should always be true. Static analysis never executes anything and needs nothing from you but the code.

What percentage of smart contract bugs do automated tools catch?

In a 2024 study of 127 high-impact attacks worth $2.3 billion, five leading tools could have prevented 8% of them, worth $149 million, and every one of those was a reentrancy bug. A 2023 study of 516 exploitable bugs found that more than 80% were beyond existing tools altogether. A 2020 evaluation of nine tools found that all of them combined detected 42% of a benchmark set of annotated vulnerabilities.

Does a clean Slither run mean my contract is secure?

No. It means no rule matched. Coverage is exactly the set of questions the detectors encode, the categories that account for most real losses have no detector at all, and the result describes one commit rather than your protocol.

What kinds of bugs can static analysis never find?

Five families: business logic and accounting errors, economic and incentive design flaws, problems that only appear when your contract is composed with another, governance and access-control intent, and assumptions about a price oracle. What they share is that correctness depends on what the protocol is meant to do, which is nowhere in the code.

Why do static analysis tools report so many false positives?

Because a pattern that is dangerous in one contract is deliberate in another, and the tool cannot see the difference. An evaluation across 47,518 live contracts had 97% of them flagged as vulnerable, and a survey of 23,000 contracts reported vulnerable in academic papers found only 1.98% had ever been exploited. Slither is explicit about this itself: 41 of its 100 detectors are labelled Medium confidence.

Do I still need an audit if I run static analysis in CI?

Run both, and expect different things from each. Static analysis in CI is the cheapest security you can buy and it removes an entire class of mechanical mistakes before review. A manual audit exists for the class of bug that has no rule, which the published research puts at the large majority of what actually gets exploited.

Share:

More Posts

Scan your project now for free

Tell us your security needs