Welcome to the Slither-Detector-101 tutorial series. This repository is designed to teach you how to write custom static analysis detectors for Ethereum Smart Contracts using the Slither framework.
Before diving into the levels, it is essential to understand the hierarchy Slither uses to represent a contract. Your detectors will navigate this tree:
- Contract: The top-level object containing functions and state variables.
- Function: Contains visibility, modifiers, and a list of Nodes.
- Node: An individual line or control flow statement (if, loop, expression).
- SlithIR: The Intermediate Representation where high-level Solidity is broken down into simplified instructions (e.g.,
HighLevelCall,BinaryOp).
This outline moves from basic metadata filtering to complex data-flow and dependency analysis.
Objective: Find functions with specific names.
- Learning: Iterating through
contract.functions. - Task: Flag any function named
debug_kill()ortest_reset()left in production.
Objective: Identify unprotected entry points.
- Learning: Checking
f.visibilityandf.modifiers. - Task: Flag
public/externalfunctions that modify state but lack anonlyOwneroronlyRolemodifier.
Objective: Find loops prone to DoS.
- Learning: Identifying dynamic loop size.
- Task: Detect
forloops that iterate over a dynamic array length (e.g.,users.length).
Objective: Ensure state changes are logged.
- Learning: Using
function.state_variables_written. - Task: Flag functions that update a
balancemapping without emitting a correspondingTransferorUpdateevent.
Objective: Validate standard implementation.
- Learning: Comparing function signatures and return types.
- Task: Verify if a contract claiming to be ERC20 implements
transferwith the correctboolreturn type.
Objective: Analyze low-level operations.
- Learning: Iterating through
node.irs(Intermediate Representation). - Task: Detect the use of the
SELFDESTRUCTopcode(SOLIDITY_CALL selfdestruct(address)in slitherIR), regardless of the variable names used in Solidity.
Objective: Analyze function requirements.
- Learning: Filtering nodes for
SolidityCalltorequire()orrevert(). - Task: Flag functions that perform an external
callwithout a precedingrequire()check.
Objective: Identify "Check-Effects-Interactions" violations.
- Learning: Sequencing
HighLevelCallvs.StateVariableWrite. - Task: Alert if a state variable is written to after an external call occurs within the same function.
Objective: Track user input to sensitive sinks.
- Learning: Using
Slither.contextandis_dependent(). - Task: Determine if a user-provided
addressargument is used as the target of alow_level_call.
Objective: Detect vulnerabilities spanning multiple calls.
- Learning: Advanced state-tracking across the contract.
- Task: Identify uninitialized proxy vulnerabilities where a global
initializedboolean is not checked in a sensitivesetup()function.
- Explore: Each folder
level-0xcontains adetector.pyand avulnerable.sol. - Run: Execute the detector using:
uv run ./level-01-metadata/detector.py- Debug: Use
slither-read-contract vulnerable.sol --print nodesto see the IR tree.