https://github.com/patrickd-/solidity-fuzzing-boilerplate
Template repository intended to ease fuzzing components of Solidity projects, especially libraries.
https://github.com/patrickd-/solidity-fuzzing-boilerplate
Last synced: 5 months ago
JSON representation
Template repository intended to ease fuzzing components of Solidity projects, especially libraries.
- Host: GitHub
- URL: https://github.com/patrickd-/solidity-fuzzing-boilerplate
- Owner: patrickd-
- License: mit
- Created: 2022-04-14T10:37:29.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2023-12-25T10:27:09.000Z (over 1 year ago)
- Last Synced: 2024-08-03T13:03:33.741Z (9 months ago)
- Language: Solidity
- Homepage:
- Size: 21.5 KB
- Stars: 205
- Watchers: 3
- Forks: 24
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-web3-tools-and-dapps - Solidity Fuzzing Boilerplate - This repository contains a collection of templates for smart contracts fuzzing. (dApps directory / Fuzzing Tools)
README
# Fuzzing of PROJECT_NAME_HERE
DESCRIPTION_HERE
```
src
│
├── echidna.yaml # Configuration file for Echidna.
├── foundry.toml # Configuration file for Foundry.
├── build.sh # Buildscript for downloading, compiling, initializing, ...
├── implementation # Implementations to fuzz (downloaded by buildscript).
│ └── ...
├── expose # Expose functions of libraries for tests.
│ └── ...
├── interface # Interfaces for accessing exposers with incompatible Solidity versions.
│ └── ...
└── test # Actual fuzzing testcases.
├── ...
├── addresses.sol # Addresses of incompatible libs, generated by buildscript.
└── helpers.sol # Reusable helper functions for tests.
```## Setup
Before any fuzzing can be run, `build.sh` needs to be executed, which has the following dependencies:
- bash
- curl
- [etheno](https://github.com/crytic/etheno) and [ganache](https://github.com/trufflesuite/ganache)
- [foundry](https://book.getfoundry.sh/getting-started/installation.html)After the buildscript was successfully executed, the implementation directory should be populated, there'll be a `echidna-init.json` file and a ganache instance will still be running in the background.
## Running Echidna Fuzzing
```bash
# Simple fuzzing with Echidna:
echidna --contract Test --config echidna.yaml src/test/example/BytesLib.sol# Differential fuzzing against another implementation with incompatible Solidity version via initialization file:
echidna --contract Test --config echidna.yaml src/test/example/BytesLib-BytesUtil-diff.sol# Differential fuzzing against an executable via FFI shell command execution:
echidna --contract Test --config echidna.yaml src/test/example/BytesLib-FFI-diff.sol
```[*The FFI cheatcode is experimental in Echidna and only available when compiling with PR#750](https://github.com/crytic/echidna/pull/750)
## Running Foundry Fuzzing
```bash
# Simple fuzzing with Foundry:
forge test --match-test test_BytesLib_slice# Differential fuzzing against another implementation with incompatible Solidity version via ganache fork:
forge test --fork-url http://127.0.0.1:8545/ --match-path src/test/example/BytesLib-BytesUtil-diff.sol# Differential fuzzing against an executable via FFI shell command execution:
forge test --match-path src/test/example/BytesLib-FFI-diff.sol
```Note that forge will appear to be stuck, but it's actually running 999999999 tests as configured in [foundry.toml](foundry.toml). This is intended to be kept running on servers for hours. If you instead want to run quick tests, eg. for CI, adjust the configuration according to your needs.
## Reproducing a finding / Manual testing
```bash
# Call function of exposed library and show execution trace:
forge script --sig "slice(bytes,uint256,uint256)" --target-contract ExposedBytesLib -vvvv src/expose/example/BytesLib.sol 0x010203 1 1# Manually execute a testcase to reproduce an issue:
forge script --fork-url http://127.0.0.1:8545/ --sig "test_BytesLib_BytesUtil_diff_slice(bytes,uint256,uint256)" --target-contract Test -vvvv src/test/example/BytesLib-BytesUtil-diff.sol 0x010203 1 1
```##### ✂ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SNIP - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Solidity Fuzzing Boilerplate
This is a template repository intended to ease fuzzing components of Solidity projects, especially libraries.
- Write tests once and run them with both [Echidna](https://github.com/crytic/echidna) and [Foundry](https://book.getfoundry.sh/forge/fuzz-testing.html)'s fuzzing.
- Fuzz components that use incompatible Solidity versions by deploying those into a Ganache instance via Etheno.
- Use HEVM's FFI cheatcode to generate complex fuzzing inputs or to compare outputs with non-EVM executables while doing differential fuzzing.
- Publish your fuzzing experiments without worrying about licensing by extending the shellscript to download specific files.## How to use the Template
### 1. Check & adjust configs
Check the [echidna.yaml](echidna.yaml) and [foundry.toml](foundry.toml) configuration files.
- Turn off FFI if you don't intend to make use of shell commands from your Solidity contracts. Note that FFI is slow and should only be used as a workaround. It can be useful for testing against things that are difficult to implement within Solidity and already exist in other languages. But it can also be dangerous: Before executing tests of a project that has FFI enabled, be sure to check what commands are actually being executed. There's nothing stopping someone to write a malicious testcase and execute malware on your computer.
- Adjust the compiler optimization options to match those of the project you're fuzzing.
- The default number of test runs configured, assumes that you intend to leave these tests running for a while to find edge cases, eg. on servers. Reduce the numbers accordingly if you only want to run quick tests.
- Adjust things like sequence lengths when fuzzing contracts that have a state (where a previous transaction can impact the next one).### 2. Adjust Buildscript
Edit the [build.sh](build.sh) file and adjust it for your usecase
- Fetch the implementations that you want to apply fuzzing on.
- During RECORDing, deploy contracts of incompatible Solidity versions in order to access them during tests.
- If you're not dealing with any contracts of incompatible versions, you can simply omit the RECORD and DEPLOY calls.### 3. Create testcases and exposers/interfaces as needed
Take a look at the [example testcases](src/test/example) and write your own.
### 4. Adjust the README.md
Don't forget to document the intention, setup and commands for your fuzzing campaign.