Foundry + Slither Setup for Smart Contract Security (2026)
A Foundry Slither tutorial for hunters is mostly terminal work: install the toolchain, compile a tiny intentional bug, run static analysis, and learn what to ignore. This Andrax guide — by Syed Zada Abrar — covers ~20% theory, ~80% practical.
Prerequisites: Wallet, RPC & Explorer; Solidity Essentials; Hub; How to Start Web3 Bug Hunting in 2026. Also complete: How to Read Verified and Unverified Smart Contracts.
Ethics fence: every vulnerable contract below is ILLUSTRATIVE / local lab only. Run Slither and Foundry tests on your machine. Anvil local forks are for hypothesis testing inside authorized bounty scope or CTFs — never to drain live protocols. Immunefi bans mainnet/public-testnet testing of in-scope code (rules).
Primary references: Foundry Book, Foundry installation, Slither, Slither usage wiki, Aderyn overview, Aderyn GitHub.
Why this stack (short theory)
| Tool | Role for hunters |
|---|---|
| Forge | Compile, unit/fuzz/invariant tests, local PoCs |
| Cast | Read chain data, decode calldata, storage (contract-reading guide) |
| Anvil | Local node; optional --fork-url for local fork state |
| Slither | AST-based static detectors (Trail of Bits / Crytic) |
| Aderyn (optional) | Fast Rust static analyzer from Cyfrin — second opinion |
Static analyzers are triage accelerators, not proof of impact. They produce candidates. You still write a Foundry test that shows funds-at-risk (or whatever the program’s IVS requires) on a local setup.
Lab 0 — Install Foundry (foundryup)
Follow the official install path (docs):
curl -L https://getfoundry.sh/install | bash
# open a new shell, or source your profile, then:
foundryup
forge --version
cast --version
anvil --version
If your environment blocks the installer script, use the precompiled binaries path from the same docs page. Confirm all three binaries print a version.
Hunter hygiene:
- Do not paste private keys into shell history for “quick tests”
- Prefer a dedicated Linux/macOS user or VM for hunting tooling
- Keep
ETH_RPC_URLin your shell env or a local.envthat is gitignored
Lab 1 — forge init an audit-style workspace
mkdir -p ~/labs && cd ~/labs
forge init fragile-vault --no-commit
cd fragile-vault
You get the standard layout (src/, test/, script/, foundry.toml). Delete or ignore the default Counter demo if you want a clean lab — or keep it and add files beside it.
Drop in an intentional vulnerable vault (local only)
Create src/FragileVault.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/// @title FragileVault
/// @notice ILLUSTRATIVE / LOCAL LAB ONLY — intentional CEI bug. Do not deploy to a public network.
contract FragileVault {
mapping(address => uint256) public balances;
function deposit() external payable {
balances[msg.sender] += msg.value;
}
function withdraw() external {
uint256 bal = balances[msg.sender];
require(bal > 0, "no balance");
// BUG: interaction before effect — classic reentrancy window
(bool ok, ) = msg.sender.call{value: bal}("");
require(ok, "send failed");
balances[msg.sender] = 0;
}
}
Compile:
forge build
You now have artifacts Slither can consume via crytic-compile / Foundry integration.
Lab 2 — Slither in a Python venv
Slither is a Python package. Prefer an isolated venv (versions clash less with system Python):
cd ~/labs/fragile-vault
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install --upgrade pip
pip install slither-analyzer
slither --version
Run against the Foundry project root (usage wiki):
slither .
You should see detectors fire. For a vault that sends ETH before zeroing balances, look for reentrancy-related findings (detector names evolve — read the message + source location, not only the severity emoji).
Triage literacy (do this every run)
- Filter noise —
--exclude-informational --exclude-lowwhen you want Medium+ first; or--exclude naming-convention,solc-versionstyle filters (wiki). - Path filter —
--filter-paths lib/|node_modules/so dependency findings do not drown your vault. - Triage mode —
slither . --triage-modeto hide accepted false positives intoslither.db.jsonfor the next run. - Never file a bounty from Slither text alone — reproduce with
forge test(next spoke for reentrancy PoC depth).
Optional JSON export for notes:
slither . --json slither-report.json
Lab 3 — Minimal Foundry test scaffold (still local)
Add test/FragileVault.t.sol so your toolchain loop is compile → test → static:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "../src/FragileVault.sol";
/// ILLUSTRATIVE — local Foundry test only
contract FragileVaultTest is Test {
FragileVault vault;
function setUp() public {
vault = new FragileVault();
}
function test_depositUpdatesBalance() public {
vault.deposit{value: 1 ether}();
assertEq(vault.balances(address(this)), 1 ether);
}
}
forge test -vv
You are not writing the full reentrancy attacker yet — that is the reentrancy guide. Today you prove the install path works end-to-end.
Optional Lab 4 — Aderyn as a second pass
Aderyn is Cyfrin’s open-source Rust static analyzer: fast CLI, Markdown/JSON reports, Foundry/Hardhat friendly (GitHub). Treat it as a complement to Slither, not a replacement.
Install via the method documented on the Aderyn overview / repo for your OS (Cyfrinup, package managers, or release binaries — follow current docs so this page does not drift). Then from the project root:
aderyn --version
aderyn .
# often writes report.md — open it and compare themes with Slither
Aderyn vs Slither (hunter framing)
| Slither | Aderyn | |
|---|---|---|
| Language / runtime | Python | Rust |
| Strength | Mature detector set, printers, triage DB | Speed, clean reports, custom detectors, editor workflows |
| Use together? | Yes — different false-positive personalities | Same |
If one tool screams and the other is silent, that is a signal to read the code, not to tweet a Critical.
Anvil: local node and local forks
Start a blank local chain:
anvil
# RPC at 127.0.0.1:8545 — use Anvil's printed test keys ONLY on this local node
Fork into Anvil (state copied locally; your experiments hit Anvil, not the remote mempool):
anvil --fork-url $ETH_RPC_URL
Rules of engagement for forks:
- OK: reading storage, simulating calls, developing PoCs for in-scope programs or CTFs on the fork
- Not OK: using the fork as emotional cover to then broadcast the same exploit on mainnet
- Not OK: “testing” live user funds on public testnets of bounty targets (Immunefi rules)
Foundry tests can also fork inside foundry.toml / cheatcodes (vm.createSelectFork) — keep those tests offline until you understand scope.
Suggested foundry.toml notes for labs
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc_version = "0.8.20"
optimizer = true
optimizer_runs = 200
# Optional later — only when you intentionally fork in tests
# [rpc_endpoints]
# mainnet = "${ETH_RPC_URL}"
Pin a solc version so Slither and Forge agree. solc-select helps if you also analyze Etherscan addresses with slither <address> (wiki).
Daily hunter loop (after install)
- Clone or
forge initthe target locally forge buildslither .(+ optionaladeryn .)- Manual notes from the Solidity and contract-reading guides checklists
- Hypothesis →
forge test/ Anvil fork simulation - Report only with runnable local PoC (later spokes)
Common install & workflow traps
| Trap | Fix |
|---|---|
| Slither on system Python breaks | Use .venv |
Running slither without forge build artifacts | Build first; fix remappings |
| Filing every High from Slither | Reproduce + impact proof |
Committing .env with RPC keys / private keys | .gitignore immediately |
| Using Anvil default keys on a public network | Those keys are famous — local only |
| Skipping path filters on huge monorepos | --filter-paths dependencies |
Remappings, libs, and “Slither can’t find OpenZeppelin”
Real audit targets pull libraries. In Foundry:
forge install OpenZeppelin/openzeppelin-contracts --no-commit
Then ensure remappings.txt (or foundry.toml remappings) points eng_echo= at the installed path. If Slither fails with missing imports, fix remappings first — do not silence the error by analyzing a half-compiled tree.
Hunter tip: run forge remappings and paste the output into notes for that repo. Inconsistent remappings are a classic “works on my machine / CI red” footgun.
What to do with a noisy Slither report
A first slither . on a DeFi monorepo can dump dozens of findings. Use a written triage table:
| Finding | Detector | In my code or dep? | Plausible impact? | Next action |
|---|---|---|---|---|
| … | reentrancy-eth | src/Vault.sol | Yes — needs PoC | Write forge test |
| … | naming-convention | src/ | No | Exclude / triage hide |
| … | arbitrary-send-eth | lib/… | Dependency | Filter path |
Severity labels from tools are hints. Immunefi and contest judges care about impact you can demonstrate. The bug-report guide will force the report structure; today, practice the discipline of “candidate → local proof or discard.”
Printers worth knowing (optional):
slither . --print human-summary
slither . --print inheritance-graph
Inheritance graphs help when the Solidity essentials guide’s “bug is in the parent” instinct triggers (printers).
CI mindset (without shipping malware)
Many teams run Slither/Aderyn in GitHub Actions on every PR. As a hunter you mirror that locally:
- Fresh clone
- Pin toolchain versions in your notes (
forge --version,slither --version,aderyn --version) - Save
slither-report.json/report.mdnext to your manual notebook - Diff reports when the protocol pushes a fix commit
Do not automate spam submissions from raw analyzer JSON — platforms reject that pattern and it wastes triage time.
Local fork recipes (safe patterns)
# Read-only exploration on a fork (still local Anvil process)
anvil --fork-url $ETH_RPC_URL --fork-block-number 19000000
# In another terminal — eth_call style reads against Anvil
cast call 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 "totalSupply()(uint256)" --rpc-url http://127.0.0.1:8545
When a bounty scope allows fork testing, keep broadcasts disabled until you have written authorization and a report draft. Prefer forge test with vm.createSelectFork inside the test process so nothing accidentally hits --broadcast.
Hardhat mention (one paragraph)
Some in-scope repos are Hardhat-first. You can still analyze them with Slither (slither . in a Hardhat project after dependencies install) and optionally keep Foundry tests in a parallel folder. This curriculum standardizes on Foundry for PoCs because forge traces and cheatcodes are the industry default for runnable Web3 reports in 2026 — but do not refuse a target just because hardhat.config.js exists.
Cheatcodes you will touch next (preview only)
You do not need the full cheatcode encyclopedia today, but know these names exist for the next guides PoCs (Foundry Book):
vm.deal— set ETH balance for a test addressvm.prank/vm.startPrank— setmsg.senderfor callsvm.expectRevert— assert a fix blocks the attackvm.createSelectFork— run a test against forked state inside Forge (still local process)
Practice deal + prank on FragileVault deposits from two addresses before you write an attacker contract. Clean tests make reentrancy traces readable.
Environment checklist (print and tape to the monitor)
-
forge,cast,anvilversions recorded - Python venv with
slither-analyzer - Optional
aderynbinary -
ETH_RPC_URLset for read-only / fork labs (never committed) -
.gitignoreincludes.env,cache/,out/,slither.db.jsonif you do not want triage noise in git - One intentional vulnerable vault compiles and
forge testpasses a happy-path deposit test -
slither .produces at least one finding you can explain in plain English - You can explain Anvil fork vs mainnet broadcast to a beginner without hand-waving
When every box is checked, you are ready for the reentrancy guide’s full reentrancy PoC — not before.
Next steps
- Prev: How to Read Verified and Unverified Smart Contracts
- Live siblings: Solidity Essentials · Wallet/RPC setup · Hub
- Next: Solidity Reentrancy Explained (Classic, Cross-Function, Read-Only) — you will turn
FragileVaultinto a classic CEI PoC on Anvil/local only. - Optional: skim Cyfrin Updraft Security course alongside this written path (Updraft)
Educational content by Syed Zada Abrar for Andrax (andraxpentester.in). Authorized research only.