Grammar-based smart-contract fuzzer from Crytic. Generates random call sequences against Solidity contracts to falsify Boolean properties, Solidity assertions, or invariants, with shrinking, coverage-guided mutation, and corpus replay.
- 01property-based testing
- 02invariant fuzzing of stateful systems
- 03assertion checking under arbitrary call sequences
- 04differential testing vs. a reference implementation
- 05regression corpora in CI
- brew install echidna
- # or download static binary from https://github.com/crytic/echidna/releases
- # Docker: docker pull ghcr.io/crytic/echidna/echidna:latest
Use Echidna for property and assertion fuzzing. Write properties as `function echidna_no_underflow() public view returns (bool) { return totalSupply >= burned; }` and run `echidna . --contract MyHarness --config echidna.yaml`. For Foundry-style assertions use `testMode: assertion` in the YAML so any failed `assert(...)` reverts a test. For long campaigns set `testLimit: 500000`, `seqLen: 100`, persist `corpusDir: corpus/` for replay, and use `--format json` in CI. Combine with `crytic-compile` so Echidna inherits the same Foundry/Hardhat build.
- ⚑Default `seqLen: 100` is too short for stateful protocols — increase it and pin a `corpusDir` so coverage compounds across runs.
- ⚑Echidna fuzzes addresses from a small pool (`SENDER`); if your invariant depends on a specific caller, set `sender:` in the YAML or your property will silently never trigger.
- ⚑Gas costs measured under instrumented fuzzing are not representative — never use Echidna runs to estimate production gas.
- ⚑Reverts are by default treated as benign; enable `allContracts: true` and assertion mode to catch unexpected reverts as failures.
- ⚑`view`/`pure` property functions are sampled but not state-checked between calls — for true invariants use `testMode: invariant` (≥ 2.2) or assertion mode.