Fuzzing
Fuzzing is the process of providing random data to programs to identify unexpected behavior, such as crashes and panics.
Fuzz tests can also be written as property tests that instead of seeking to identify panics and crashes, assert on some property remaining true. Fuzzing as demonstrated here and elsewhere in these docs will use principles from both property testing and fuzzing, but will only use the term fuzzing to refer to both.
The following steps can be used in any Stellar contract workspace. If experimenting, try them in the increment example. The contract has an increment function that increases a counter value by one on every invocation.
How to Write Fuzz Tests
-
Install the nightly Rust toolchain. Nightly Rust is required to run cargo-fuzz.
rustup install nightly -
Install
cargo-fuzz.cargo install --locked cargo-fuzz -
Initialize a fuzz project by running the following command inside your contract directory.
cargo fuzz init -
Open the contract's
Cargo.tomlfile. Addlibas acrate-type.[lib]-crate-type = ["cdylib"]+crate-type = ["lib", "cdylib"] -
Open the generated
fuzz/Cargo.tomlfile. Add thesoroban-sdkdependency.[dependencies]libfuzzer-sys = "0.4"+soroban-sdk = { version = "*", features = ["testutils"] } -
Open the generated
fuzz/src/fuzz_target_1.rsfile. It will look like the below.#![no_main]use libfuzzer_sys::fuzz_target;fuzz_target!(|data: &[u8]| {// fuzzed code goes here}); -
Fill out the
fuzz_target!call with test setup and assertions. For example, for the increment example:#![no_main]use libfuzzer_sys::fuzz_target;use soroban_increment_with_fuzz_contract::{IncrementContract, IncrementContractClient};use soroban_sdk::{testutils::arbitrary::{arbitrary, Arbitrary},Env,};#[derive(Debug, Arbitrary)]pub struct Input {pub by: u64,}fuzz_target!(|input: Input| {let env = Env::default();let id = env.register(IncrementContract, ());let client = IncrementContractClient::