Static Analysis Skill
Integrate automated static analysis tools into the audit workflow to catch low-hanging vulnerabilities before manual review. Static analysis should be the FIRST step after compilation — it surfaces issues that automated tools excel at finding, freeing manual review time for complex logic and economic vulnerabilities.
Why Static Analysis First?
| Benefit |
Details |
| Coverage baseline |
Ensures known vulnerability patterns are checked across ALL functions |
| Prioritization |
Findings direct manual reviewer to highest-risk areas |
| Speed |
Minutes vs hours/days for manual review |
| Consistency |
Never misses a pattern it knows about (humans do) |
| Documentation |
Generates structured output for audit reports |
Detection Capabilities
What Static Analysis Catches Well
| Category |
Examples |
| Reentrancy |
All variants: ETH, ERC-20, cross-function, read-only |
| Unchecked calls |
Missing return value checks on transfer, send, low-level call |
| Access control |
Unprotected selfdestruct, missing modifiers, tx.origin auth |
| State issues |
Uninitialized storage, shadowed variables, redundant state |
| Dangerous patterns |
Controlled delegatecall, hardcoded gas, block.timestamp dependency |
| Code quality |
Floating pragma, unused variables, dead code, naming conventions |
| Standard compliance |
ERC-20 / ERC-721 interface compliance |
| Compiler issues |
Use of deprecated patterns, assembly without memory safety |
What Static Analysis Misses
| Category |
Why |
| Business logic |
Tools don't understand protocol semantics |
| Economic attacks |
Flash loan manipulation, oracle gaming |
| Cross-contract interactions |
Limited to single-contract analysis (mostly) |
| Governance attacks |
Vote manipulation, proposal hijacking |
| MEV / sandwich |
Requires mempool context |
| Timing attacks |
Cross-block state dependencies |
| Complex math errors |
Rounding, precision loss in multi-step calculations |
Tool Comparison
| Tool |
Language |
Approach |
Speed |
False Positives |
Best For |
| Slither |
Python |
AST + data flow |
Fast (seconds) |
Low-Medium |
Broad vulnerability detection, code quality |
| Mythril |
Python |
Symbolic execution + SMT |
Slow (minutes-hours) |
Low |
Deep state reachability, proving exploitability |
| Aderyn |
Rust |
AST analysis |
Very fast |
Low |
Quick scans, CI/CD integration |
| Semgrep |
Python |
Pattern matching |
Fast |
Depends on rules |
Custom rules, org-specific patterns |
| Foundry invariant tests |
Solidity |
Fuzzing |
Medium |
Very low |
Invariant verification |
| Echidna |
Haskell |
Property-based fuzzing |
Slow |
Very low |
Finding edge cases in complex state |
| Medusa |
Go |
Parallel fuzzing |
Medium |
Very low |
Faster alternative to Echidna |
Recommended Workflow
1. Slither (always — fast, broad coverage)
│
2. Aderyn (always — fast, complementary detectors)
│
3. Semgrep with custom rules (if org has rules)
│
4. Mythril (selectively — on high-risk functions only)
│
5. Echidna/Medusa (if invariant tests needed)
Slither Quick Reference
Installation
pip install slither-analyzer
# Requires solc installed (managed by solc-select)
pip install solc-select
solc-select install 0.8.20
solc-select use 0.8.20
Common Commands
# Full scan
slither .
# Filter out dependencies
slither . --filter-paths "node_modules|lib|test"
# Specific detectors
slither . --detect reentrancy-eth,arbitrary-send-eth,controlled-delegatecall
# JSON output
slither . --json output.json
# Code analysis printers
slither . --print contract-summary
slither . --print function-summary
slither . --print inheritance-graph
slither . --print call-graph
slither . --print variable-order # Storage layout
Aderyn Quick Reference
Installation
cargo install aderyn
# Or via npm
npm install -g aderyn
Usage
# Full scan
aderyn .
# Specific scope
aderyn . --src src/
# Markdown output
aderyn . --output report.md
Key Detectors
| Detector |
Description |
centralization-risk |
Functions callable by single address |
unsafe-erc20-functions |
Direct transfer/approve without Safe wrapper |
push-0 |
PUSH0 opcode incompatible with older EVM versions |
solmate-safe-transfer-lib |
Solmate SafeTransferLib doesn't check contract existence |
unprotected-init |
Missing initializer guard |
Semgrep Quick Reference
# Install
pip install semgrep
# Run with Solidity rules
semgrep --config "p/solidity" .
# Custom rule example
semgrep --config custom-rules/ .
Custom Rule Example
rules:
- id: unchecked-low-level-call
patterns:
- pattern: |
(bool $SUCCESS, ) = $ADDR.call{...}(...);
- pattern-not-inside: |
require($SUCCESS, ...);
message: "Low-level call return value not checked"
severity: ERROR
languages: [solidity]
Resources
- Slither Guide — Full configuration, detectors, triage
Workflows
- Static Analysis Workflow — Step-by-step process
1---2name: static-analysis3description: Integrate automated static analysis tools (Slither, Mythril, Aderyn, Semgrep) into the audit workflow to catch known vulnerability patterns before manual review. Use when starting an audit to establish a coverage baseline, or when configuring static analysis tooling for a project.4---56# Static Analysis Skill78Integrate automated static analysis tools into the audit workflow to catch low-hanging vulnerabilities before manual review. Static analysis should be the FIRST step after compilation — it surfaces issues that automated tools excel at finding, freeing manual review time for complex logic and economic vulnerabilities.910---1112## Why Static Analysis First?1314| Benefit | Details |15|---------|--------|16| Coverage baseline | Ensures known vulnerability patterns are checked across ALL functions |17| Prioritization | Findings direct manual reviewer to highest-risk areas |18| Speed | Minutes vs hours/days for manual review |19| Consistency | Never misses a pattern it knows about (humans do) |20| Documentation | Generates structured output for audit reports |2122---2324## Detection Capabilities2526### What Static Analysis Catches Well2728| Category | Examples |29|----------|----------|30| Reentrancy | All variants: ETH, ERC-20, cross-function, read-only |31| Unchecked calls | Missing return value checks on `transfer`, `send`, low-level `call` |32| Access control | Unprotected `selfdestruct`, missing modifiers, `tx.origin` auth |33| State issues | Uninitialized storage, shadowed variables, redundant state |34| Dangerous patterns | Controlled `delegatecall`, hardcoded gas, `block.timestamp` dependency |35| Code quality | Floating pragma, unused variables, dead code, naming conventions |36| Standard compliance | ERC-20 / ERC-721 interface compliance |37| Compiler issues | Use of deprecated patterns, assembly without memory safety |3839### What Static Analysis Misses4041| Category | Why |42|----------|-----|43| Business logic | Tools don't understand protocol semantics |44| Economic attacks | Flash loan manipulation, oracle gaming |45| Cross-contract interactions | Limited to single-contract analysis (mostly) |46| Governance attacks | Vote manipulation, proposal hijacking |47| MEV / sandwich | Requires mempool context |48| Timing attacks | Cross-block state dependencies |49| Complex math errors | Rounding, precision loss in multi-step calculations |5051---5253## Tool Comparison5455| Tool | Language | Approach | Speed | False Positives | Best For |56|------|----------|----------|-------|----------------|----------|57| **Slither** | Python | AST + data flow | Fast (seconds) | Low-Medium | Broad vulnerability detection, code quality |58| **Mythril** | Python | Symbolic execution + SMT | Slow (minutes-hours) | Low | Deep state reachability, proving exploitability |59| **Aderyn** | Rust | AST analysis | Very fast | Low | Quick scans, CI/CD integration |60| **Semgrep** | Python | Pattern matching | Fast | Depends on rules | Custom rules, org-specific patterns |61| **Foundry invariant tests** | Solidity | Fuzzing | Medium | Very low | Invariant verification |62| **Echidna** | Haskell | Property-based fuzzing | Slow | Very low | Finding edge cases in complex state |63| **Medusa** | Go | Parallel fuzzing | Medium | Very low | Faster alternative to Echidna |6465### Recommended Workflow6667```681. Slither (always — fast, broad coverage)69 │702. Aderyn (always — fast, complementary detectors)71 │723. Semgrep with custom rules (if org has rules)73 │744. Mythril (selectively — on high-risk functions only)75 │765. Echidna/Medusa (if invariant tests needed)77```7879---8081## Slither Quick Reference8283### Installation8485```bash86pip install slither-analyzer87# Requires solc installed (managed by solc-select)88pip install solc-select89solc-select install 0.8.2090solc-select use 0.8.2091```9293### Common Commands9495```bash96# Full scan97slither .9899# Filter out dependencies100slither . --filter-paths "node_modules|lib|test"101102# Specific detectors103slither . --detect reentrancy-eth,arbitrary-send-eth,controlled-delegatecall104105# JSON output106slither . --json output.json107108# Code analysis printers109slither . --print contract-summary110slither . --print function-summary111slither . --print inheritance-graph112slither . --print call-graph113slither . --print variable-order # Storage layout114```115116---117118## Aderyn Quick Reference119120### Installation121122```bash123cargo install aderyn124# Or via npm125npm install -g aderyn126```127128### Usage129130```bash131# Full scan132aderyn .133134# Specific scope135aderyn . --src src/136137# Markdown output138aderyn . --output report.md139```140141### Key Detectors142143| Detector | Description |144|----------|-----------|145| `centralization-risk` | Functions callable by single address |146| `unsafe-erc20-functions` | Direct `transfer`/`approve` without Safe wrapper |147| `push-0` | `PUSH0` opcode incompatible with older EVM versions |148| `solmate-safe-transfer-lib` | Solmate SafeTransferLib doesn't check contract existence |149| `unprotected-init` | Missing initializer guard |150151---152153## Semgrep Quick Reference154155```bash156# Install157pip install semgrep158159# Run with Solidity rules160semgrep --config "p/solidity" .161162# Custom rule example163semgrep --config custom-rules/ .164```165166### Custom Rule Example167168```yaml169rules:170 - id: unchecked-low-level-call171 patterns:172 - pattern: |173 (bool $SUCCESS, ) = $ADDR.call{...}(...);174 - pattern-not-inside: |175 require($SUCCESS, ...);176 message: "Low-level call return value not checked"177 severity: ERROR178 languages: [solidity]179```180181---182183## Resources184- [Slither Guide](resources/slither-guide.md) — Full configuration, detectors, triage185186## Workflows187- [Static Analysis Workflow](workflows/static-analysis.md) — Step-by-step process