# Aderyn — The New Rust-Based Static Analyzer for Solidity
Static analysis has become non-negotiable in smart contract development. While Slither has been the gold standard for years, a new contender has emerged: Aderyn, a Rust-based analyzer built by Cyfrin that's faster, easier to install, and designed specifically for modern Solidity workflows.
What Is Aderyn?
Aderyn is a static analysis tool that scans Solidity code for vulnerabilities, gas inefficiencies, and code quality issues — without executing the code. Think of it as a super-powered linter that understands blockchain-specific security patterns.
Key features:
- Written in Rust: 10-50x faster than Python-based tools
- Zero Python dependencies: Single binary installation
- Modern Solidity support: Built for 0.8+ with custom types, user-defined operators
- Foundry-native: Deep integration with Foundry projects
- Markdown reports: Beautiful, shareable audit reports
- Extensible: Easy to add custom detectors
Installation
macOS / Linux
# Install via cargo
cargo install aderyn
# Or download pre-built binary
curl -L https://github.com/Cyfrin/aderyn/releases/latest/download/aderyn-x86_64-unknown-linux-gnu -o aderyn
chmod +x aderyn
sudo mv aderyn /usr/local/bin/
# Verify installation
aderyn --version
Windows
# Download from releases
# https://github.com/Cyfrin/aderyn/releases
# Or via cargo
cargo install aderyn
Foundry Projects (Recommended)
# Add to foundryup
foundryup --install-aderyn
# Or as a Foundry dependency
forge install cyfrin/aderyn
That's it. No Python virtual environments, no pip dependency hell, no PATH configuration. Just a single binary.
Basic Usage
Scan a Project
# Basic scan
aderyn .
# Scan specific directory
aderyn ./src
# Output to file
aderyn . --output report.md
# JSON output for CI
aderyn . --format json > aderyn-report.json
Example Output
# Aderyn Analysis Report
Summary
- Files Analyzed: 12
- Issues Found: 8
- Critical: 1
- High: 2
- Medium: 3
- Low: 2
Critical Issues
Unprotected Ether Withdrawal
File: src/Vault.sol:45
Severity: Critical
solidity
function withdraw() public {
payable(msg.sender).transfer(address(this).balance);
}
Issue: Anyone can drain the contract
Recommendation: Add access control
High Issues
Reentrancy Vulnerability
File: src/DEX.sol:78
...
Real-World Example
Let's analyze a simple DeFi contract:
// src/Staking.sol
pragma solidity ^0.8.0;
contract Staking {
mapping(address => uint256) public stakes;
mapping(address => uint256) public rewards;
function stake() public payable {
stakes[msg.sender] += msg.value;
updateRewards(msg.sender);
}
function withdraw(uint256 amount) public {
require(stakes[msg.sender] >= amount);
stakes[msg.sender] -= amount;
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
updateRewards(msg.sender);
}
function updateRewards(address user) internal {
rewards[user] += stakes[user] / 100;
}
function claimRewards() public {
uint256 reward = rewards[msg.sender];
rewards[msg.sender] = 0;
(bool success, ) = msg.sender.call{value: reward}("");
require(success);
}
}
Run Aderyn:
aderyn src/
Aderyn's findings:
## High Severity
H-1: Reentrancy in withdraw()
Location: src/Staking.sol:15-20
The function updates state after external call, allowing reentrancy:
solidity
stakes[msg.sender] -= amount;
(bool success, ) = msg.sender.call{value: amount}(""); // External call
require(success);
updateRewards(msg.sender); // State change after external call
Impact: Attacker can drain contract via reentrancy
Recommendation: Use checks-effects-interactions pattern
H-2: Reentrancy in claimRewards()
Location: src/Staking.sol:26-30
Same reentrancy pattern.
Medium Severity
M-1: Unbounded Gas Consumption
Location: src/Staking.sol:23
updateRewards() called in every operation could become expensive.
M-2: Integer Division Truncation
Location: src/Staking.sol:24
stakes[user] / 100 loses precision for small stakes.
Low Severity
L-1: Missing Event Emission
Functions should emit events for off-chain tracking.
L-2: No Input Validation
withdraw() doesn't check for zero amount.
Aderyn vs Slither Comparison
| Feature | Aderyn | Slither |
|---------|--------|---------|
| Language | Rust | Python |
| Installation | Single binary | pip + dependencies |
| Speed | 10-50x faster | Baseline |
| Solidity Support | 0.8+ focused | 0.4+ comprehensive |
| Foundry Integration | Native | Plugin |
| Report Format | Markdown, JSON | Text, JSON, SARIF |
| Custom Detectors | Rust plugins | Python scripts |
| False Positives | Lower (newer) | Higher (mature) |
| Detectors | ~50 | ~90 |
| CI Integration | Built-in | Requires setup |
Speed Benchmark
On a 50-file DeFi project:
# Slither
time slither .
# real 0m45.230s
# Aderyn
time aderyn .
# real 0m1.892s
Aderyn is 24x faster.
Detection Quality
Both tools catch the same critical issues, but with different strengths:
Aderyn excels at:
- Modern Solidity patterns (custom types, user-defined operators)
- Gas optimization
- Foundry-specific issues
- Fewer false positives
Slither excels at:
- Legacy Solidity (0.4, 0.5)
- More detector variety
- Research-backed detectors
- Cross-contract analysis
CI/CD Integration
GitHub Actions
# .github/workflows/security.yml
name: Security Analysis
on: [push, pull_request]
jobs:
aderyn:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Aderyn
run: |
curl -L https://github.com/Cyfrin/aderyn/releases/latest/download/aderyn-x86_64-unknown-linux-gnu -o aderyn
chmod +x aderyn
sudo mv aderyn /usr/local/bin/
- name: Run Aderyn
run: aderyn . --format json > aderyn-report.json
- name: Check for critical issues
run: |
CRITICAL=$(jq '.issues[] | select(.severity == "Critical") | length' aderyn-report.json)
if [ "$CRITICAL" -gt 0 ]; then
echo "Critical issues found!"
exit 1
fi
- name: Upload report
uses: actions/upload-artifact@v3
with:
name: aderyn-report
path: aderyn-report.json
GitLab CI
# .gitlab-ci.yml
aderyn:
stage: test
image: rust:latest
before_script:
- cargo install aderyn
script:
- aderyn . --format json > aderyn-report.json
- |
if jq -e '.issues[] | select(.severity == "Critical")' aderyn-report.json; then
echo "Critical issues found"
exit 1
fi
artifacts:
reports:
junit: aderyn-report.json
Pre-commit Hook
# .git/hooks/pre-commit
#!/bin/bash
echo "Running Aderyn..."
aderyn . --format json > /tmp/aderyn-report.json
CRITICAL=$(jq '.issues[] | select(.severity == "Critical") | length' /tmp/aderyn-report.json)
HIGH=$(jq '.issues[] | select(.severity == "High") | length' /tmp/aderyn-report.json)
if [ "$CRITICAL" -gt 0 ] || [ "$HIGH" -gt 0 ]; then
echo "Security issues found!"
jq '.issues[] | select(.severity == "Critical" or .severity == "High")' /tmp/aderyn-report.json
exit 1
fi
echo "Aderyn check passed"
Custom Detectors
Aderyn allows custom detectors in Rust:
// my_detector.rs
use aderyn::{Detector, Issue, Severity};
pub struct UnprotectedInitializer;
impl Detector for UnprotectedInitializer {
fn detect(&self, context: &Context) -> Vec<Issue> {
let mut issues = vec![];
for function in context.functions() {
if function.name.contains("initialize")
&& !function.has_modifier("initializer") {
issues.push(Issue {
severity: Severity::High,
title: "Unprotected initializer".to_string(),
description: format!(
"Function {} lacks initializer protection",
function.name
),
location: function.location.clone(),
});
}
}
issues
}
}
Configuration
Create aderyn.toml:
[aderyn]
# Ignore specific detectors
ignore = [
"missing-events",
"naming-convention"
]
# Set severity thresholds
fail_on = "high" # Fail CI on high+ severity
# Exclude files/directories
exclude = [
"test/**",
"script/**",
"lib/**"
]
# Custom detector path
detectors = "./custom-detectors"
# Report format
output_format = "markdown"
output_file = "security-report.md"
Best Practices
1. Run on Every Commit
# Makefile
.PHONY: analyze
analyze:
aderyn . --output reports/aderyn-$(shell date +%Y%m%d).md
.PHONY: ci-analyze
ci-analyze:
aderyn . --format json --fail-on high
2. Combine with Other Tools
# Run full security suite
make test # Unit tests
aderyn . # Static analysis
slither . # Second opinion
forge coverage # Coverage check
3. Review False Positives
// Mark false positives
function withdraw() public onlyOwner {
// aderyn-disable-next-line reentrancy
(bool success, ) = owner.call{value: amount}("");
require(success);
}
4. Track Issues Over Time
# Compare reports
aderyn . --format json > reports/current.json
diff reports/baseline.json reports/current.json
When to Use Aderyn vs Slither
Use Aderyn when:
- Building new projects with Solidity 0.8+
- Using Foundry
- Need fast CI/CD pipelines
- Want minimal setup
- Focused on gas optimization
Use Slither when:
- Working with legacy codebases
- Need maximum detector coverage
- Running research on vulnerabilities
- Require SARIF output for GitHub Security
Use both when:
- Preparing for audit
- Maximum security is critical
- You want defense in depth
Most teams now run both in CI and treat their intersection as must-fix issues.
Conclusion
Aderyn represents the next generation of Solidity tooling: fast, modern, and developer-friendly. While Slither remains valuable for comprehensive analysis, Aderyn's speed and ease of use make it perfect for continuous integration and rapid development cycles.
Get started today:
cargo install aderyn
aderyn --help
Your smart contracts will thank you.