What Is Mythril? Symbolic Execution for Smart Contract Security
Mythril is an open-source security analysis tool for EVM bytecode that uses symbolic execution to detect vulnerabilities in Ethereum smart contracts. Unlike linters or static analyzers that read source code and match patterns, Mythril reasons about what a contract can do by exploring all mathematically possible execution paths through its compiled bytecode. That distinction matters enormously when you are trying to find bugs that only manifest under very specific combinations of inputs and state.
Symbolic Execution vs. Static Analysis
To understand what Mythril offers, it helps to contrast it with static analysis tools like Slither. Static analysis reads the abstract syntax tree or an intermediate representation of the source code and flags constructs that match known vulnerability patterns. It is fast, relatively deterministic, and easy to integrate into CI pipelines. Its weakness is that it cannot reason about runtime values—it does not know what a variable will actually hold when a function executes.
Symbolic execution takes a different approach. Instead of assigning concrete values to variables, it assigns symbolic variables—mathematical unknowns—and then follows every branch of every conditional simultaneously. Each branch accumulates a path condition: a set of constraints that must be true for execution to reach that point. When a potentially dangerous state is encountered (say, a division or an external call before a state update), Mythril hands the accumulated constraints to an SMT solver, which determines whether a concrete input exists that satisfies all of them. If one exists, the bug is reachable and Mythril reports it.
This approach is more powerful than pattern matching for certain vulnerability classes, but it comes with its own limitations, which are covered later in this guide. For a fuller picture of the static analysis side, see What Is Slither? A Practical Guide to the Solidity Static Analyzer.
What Mythril Catches
Mythril targets a specific set of vulnerability classes that are well-suited to symbolic reasoning. The tool ships with a module system where each module checks for one class of issue.
Reentrancy
Mythril can detect reentrancy when it finds an external call followed by a storage write on the same execution path—the classic checks-effects-interactions violation. Symbolic execution lets it confirm that the external call is actually reachable before reporting.
Integer Overflow and Underflow
Before Solidity 0.8, arithmetic operations could silently wrap. Mythril explores paths where symbolic integer inputs drive arithmetic past their bounds and checks whether an overflow or underflow state is satisfiable. If you are working with pre-0.8 code or assembly blocks that bypass checked arithmetic, this detection is valuable. For a deeper explanation of the vulnerability class itself, see Integer Overflow and Underflow in Smart Contracts.
Unprotected Ether Withdrawal
Mythril checks whether an execution path allows an arbitrary caller to drain Ether from the contract. It symbolically models the caller address and verifies whether the access control constraints can be satisfied by a non-privileged account.
Delegatecall to User-Supplied Address
Passing an attacker-controlled address to delegatecall is a critical vulnerability. Mythril traces taint from msg.data or calldata through to delegatecall targets and flags paths where the address is externally influenced.
Timestamp and Block Number Dependence
When contract logic branches on block.timestamp or block.number in a way that can be influenced by a miner or validator, Mythril flags it. These checks are heuristic rather than pure symbolic proofs, but they surface real issues in on-chain randomness and time-locked logic.
Assertion Violations
Mythril searches for inputs that cause assert() statements to fail. Because assert is meant to guard invariants that should never be violated, a satisfiable counterexample is a strong signal of a logic bug.
A Practical Vulnerable Example
Consider a pre-0.8 withdrawal function with an overflow in the balance accounting:
// Vulnerable: pre-Solidity 0.8, no SafeMath
pragma solidity ^0.7.6;
contract VulnerableVault {
mapping(address => uint256) public balances;
function deposit() external payable {
balances[msg.sender] += msg.value;
}
function withdraw(uint256 amount) external {
require(balances[msg.sender] >= amount);
// State update after external call — reentrancy risk
(bool ok, ) = msg.sender.call{value: amount}("");
require(ok);
balances[msg.sender] -= amount;
}
}
Mythril would find two issues here. First, the external call to msg.sender precedes the balance deduction, making the path condition for reentrancy satisfiable. Second, if balances[msg.sender] is already zero and amount is zero, the subtraction on the last line still executes cleanly, but a symbolic attacker might manipulate the balance to underflow in a related context. Here is the corrected version following checks-effects-interactions:
// Fixed: state update before external call
function withdraw(uint256 amount) external {
require(balances[msg.sender] >= amount);
balances[msg.sender] -= amount; // effect first
(bool ok, ) = msg.sender.call{value: amount}("");
require(ok);
}
Running Mythril
Mythril can be installed via pip or Docker. The Docker approach avoids dependency conflicts and is generally recommended for teams.
# Docker (recommended)
docker pull mythril/myth
docker run mythril/myth analyze /path/to/Contract.sol --solv 0.8.20
# pip
pip3 install mythril
myth analyze Contract.sol --solv 0.8.20
Key flags worth knowing:
--execution-timeout: Sets the maximum seconds per analysis. The default is 86400 (24 hours), which is rarely practical. For most contracts, 300–600 seconds is a reasonable starting point.--max-depth: Limits the transaction depth. Higher values explore more paths but increase run time exponentially.-o json: Outputs findings as JSON, useful for CI integration.--module: Restricts analysis to specific vulnerability modules if you only care about one issue class.
Understanding Mythril's Limits
Symbolic execution is not magic, and knowing where Mythril struggles is as important as knowing what it finds.
Path Explosion
The number of execution paths in a contract grows exponentially with the number of conditional branches. Deeply nested logic, loops with symbolic bounds, or contracts that call many external functions can cause Mythril to time out before it has explored the interesting paths. Tuning --execution-timeout and --max-depth is mandatory for large contracts, and even then coverage may be incomplete.
False Positives
Mythril sometimes reports a vulnerability as reachable when real-world access control or business logic makes exploitation impossible. Every Mythril finding should be reviewed by a developer who understands the contract's intended behavior before it is treated as a confirmed bug.
False Negatives
Because of path explosion and timeouts, Mythril can miss bugs that exist on paths it never explored. It does not provide coverage guarantees. Complex multi-contract interactions are also hard for Mythril to model accurately.
No Behavioral Property Testing
Mythril cannot verify arbitrary user-defined invariants the way a fuzzer can. For property-based invariant testing, see What Is Echidna? Property-Based Fuzzing for Smart Contracts. Symbolic execution and fuzzing are complementary, not interchangeable.
Where Mythril Fits in a Security Workflow
Mythril is most valuable when used alongside other tools rather than as a standalone solution. A layered approach looks roughly like this:
- Static analysis (Slither, Aderyn, Solhint): Fast, broad coverage of code-level issues and style violations. Run on every commit.
- Symbolic execution (Mythril, SMTChecker): Deeper path-level analysis targeting specific dangerous states. Run on feature completion or release candidates.
- Fuzzing (Echidna, Medusa): Property-based invariant testing with randomly generated inputs. Run as part of integration testing.
- Manual audit: Human review of business logic, economic attack surfaces, and anything tools cannot model. Required before mainnet deployment of high-value contracts.
If you want to see Mythril results alongside output from Slither, Aderyn, Semgrep, and other tools in a single report, you can run an automated scan that executes all of them in parallel and explains each finding in plain language.
Mythril and the SMTChecker Compared
Solidity's built-in SMTChecker also uses symbolic reasoning, but it operates at the source level during compilation rather than on bytecode. The two tools are complementary: SMTChecker has better access to source-level semantics and can verify overflow safety in 0.8+ code automatically, while Mythril works on any EVM bytecode regardless of source language and is better suited to detecting reentrancy and call-based vulnerabilities. Using both gives better coverage than either alone.
Summary
Mythril brings symbolic execution to Ethereum smart contract security. It explores all possible execution paths through compiled bytecode, uses an SMT solver to determine whether dangerous states are actually reachable, and reports findings with concrete transaction traces when it finds them. It catches reentrancy, integer overflow, unprotected withdrawals, dangerous delegatecalls, and assertion violations more rigorously than pure pattern matching, but it is bounded by path explosion and cannot replace manual review of complex business logic. Used as one layer in a multi-tool security pipeline, it significantly raises the bar for finding critical vulnerabilities before deployment.
Scan your contract before you ship
Run an automated, transparent security scan — seven industry tools in parallel, every finding labeled with its source tool. It is not a substitute for a full manual audit, but it is a fast first line of defense.
Scan a contractFrequently asked questions
What is Mythril and what programming language is it written in?
Mythril is an open-source smart contract security analysis tool written in Python. It analyzes EVM bytecode using symbolic execution and an SMT solver to find reachable vulnerability states in Ethereum contracts.
How is symbolic execution different from static analysis?
Static analysis reads source code or an intermediate representation and flags patterns that resemble known vulnerabilities, without reasoning about runtime values. Symbolic execution assigns mathematical unknowns to inputs and state variables, then explores all possible execution paths to determine whether a dangerous state—such as an unauthorized Ether withdrawal—can actually be reached with a concrete input.
Can Mythril find all vulnerabilities in a smart contract?
No. Mythril is bounded by path explosion: as a contract grows in complexity, the number of paths it must explore increases exponentially. Large contracts often require strict timeouts that limit coverage. Mythril also does not verify arbitrary user-defined business logic invariants and can produce false positives that require developer review. It should be used alongside static analysis, fuzzing, and a manual audit for high-value contracts.
How long does a Mythril analysis take?
Run time varies enormously with contract complexity and the --execution-timeout setting. Small to medium contracts typically complete in a few minutes with a timeout of 300–600 seconds. Large contracts with many branches can exhaust even long timeouts without achieving full path coverage, so results should always be interpreted with that limitation in mind.
Does Mythril work on Solidity 0.8 contracts?
Yes. Mythril analyzes EVM bytecode, so it works with any Solidity version. For 0.8+ code, built-in overflow protection means Mythril will not flag overflow on standard arithmetic, but it will still detect reentrancy, unprotected withdrawals, dangerous delegatecalls, and assertion violations where those exist.