CosmFuzz uses a cosmfuzz-config.toml file to configure fuzzing behavior.
[cosmfuzz]
name = "my-fuzzer"
fuzz_dir = "/tmp/cosmfuzz" # Where fuzzing artifacts are stored
main_contract = "cw20-base" # Optional: which contract has the setup function
[[contracts]]
name = "cw20-base"
path = "../cw20-base"
entry_label = "cw20"
[fuzzing]
accounts = 5
native_denom = "uatom"
initial_balance = 1000
max_msg_count = 16
block_time_interval = 5
timeout = 60
jobs = 4- name: Name for your fuzzing project (default: parent directory name)
- fuzz_dir: Directory where fuzzing artifacts are stored (default:
/tmp/cosmfuzz) - main_contract (optional): Explicitly specify which contract is the main contract (for setup functions)
The actual fuzz directory will be: {fuzz_dir}/{name}/
The main_contract field determines which contract CosmFuzz looks in for the setup function. If not specified, CosmFuzz will:
- Use the contract whose directory contains the config file (typically path = ".")
- If that can't be determined, use the first contract in the list
Example:
[cosmfuzz]
name = "my-fuzzer"
fuzz_dir = "/tmp/cosmfuzz"
main_contract = "token-vault" # This contract should have the setup() functionThis is useful when:
- You have multiple contracts and want to be explicit about which one has the setup function
- Your config file isn't in the main contract's directory
- You want to make the configuration more self-documenting
Each contract requires:
- name: The Rust crate name (must match the package name in Cargo.toml)
- path: Relative or absolute path to the contract directory
- entry_label: Short identifier used in generated code (e.g., "cw20", "staking")
[[contracts]]
name = "cw20-base"
path = "../cw20-base"
entry_label = "cw20"
[[contracts]]
name = "cw20-staking"
path = "../cw20-staking"
entry_label = "staking"The entry_label is used:
- As the contract address variable name:
{label}_addr - In function imports:
{label}_execute,{label}_instantiate,{label}_query - As parameter names in invariant functions
All fields in the [fuzzing] section have defaults and are technically optional, but you should configure them based on your contract's needs.
- accounts (default: 5): Number of test accounts to create
- native_denom (default: "uatom"): Native token denomination
- initial_balance (default: 1000): Initial balance per account in native denom
- max_msg_count (default: 16): Maximum messages per fuzz input
- block_time_interval (default: 5): Block time increment in seconds between messages
- timeout (optional, default: none): Fuzzing timeout in seconds (maps to
-tflag) - jobs (optional, default: none): Number of parallel fuzzing jobs (maps to
-jflag)
Note: The timeout and jobs fields are only used if not overridden by command-line arguments when running cargo cosmfuzz fuzz.
[cosmfuzz]
name = "minimal"
fuzz_dir = "/tmp/cosmfuzz"
[[contracts]]
name = "minimal-example"
path = "."
entry_label = "minimal_example"
[fuzzing]
accounts = 1
native_denom = "uatom"
initial_balance = 1000
max_msg_count = 5
block_time_interval = 5
timeout = 10
jobs = 2[cosmfuzz]
name = "defi-protocol"
fuzz_dir = "/custom/path/fuzz"
main_contract = "vault-contract" # Vault contract contains the setup function
[[contracts]]
name = "token-contract"
path = "./contracts/token"
entry_label = "token"
[[contracts]]
name = "vault-contract"
path = "./contracts/vault"
entry_label = "vault"
[[contracts]]
name = "governance-contract"
path = "./contracts/governance"
entry_label = "gov"
[fuzzing]
accounts = 10
native_denom = "uosmo"
initial_balance = 10000
max_msg_count = 32
block_time_interval = 1
timeout = 300
jobs = 8By default, fuzzing artifacts are stored in /tmp/cosmfuzz/{project-name}/. This includes:
- Generated harness code (
src/main.rs) - Corpus (interesting inputs found during fuzzing)
- Crashes
- Coverage data
- Build artifacts
You can customize this with the fuzz_dir setting:
[cosmfuzz]
fuzz_dir = "./fuzz" # Store in project directoryor
[cosmfuzz]
fuzz_dir = "/home/user/fuzzing" # Custom absolute path- Paths in
contractscan be relative (to config file location) or absolute - Contract names must match exactly with the Rust crate names
- Entry labels must be valid Rust identifiers (no hyphens, use underscores)
- The config file is searched upward from the current directory