Skip to content

feat (proposal): UX for granularity over fuzz, invariant, and solidity sections #3062

@mds1

Description

@mds1

Component

Forge

Describe the feature you would like

Supersedes #744

For the [fuzz] and [invariant] sections, you must define configuration per-profile and it applies to all tests. Some tests need more/less fuzzing than others, so it would be great to configure this on a per-test basis. Below is a proposal for how to structure the foundry.toml to allow this.

Similarly, it would be great to allow different solc settings per contract (e.g. 1 optimizer run for MyBigContract but 10M optimizer runs for all others). This proposal would enable that as well.

# OVERVIEW
# Each fuzz/invariant section can have subprofiles. In these subprofiles you
# can define all the standard fuzz/invariant options, but additionally the same
# matching flags that `forge test` has are supported. This means good naming
# conventions are important to make targeting your tests easy.

# EXAMPLE
# Here is an example using fuzz configs to do the following:
#
# Default profile:
#   - 250 fuzz runs by default
#   - `low` tests execute 50 fuzz runs
#   - `high` tests execute 500 fuzz runs
# CI profile:
#   - 1000 fuzz runs by default
#   - `low` tests execute 500 fuzz runs
#   - `high` tests execute 5000 fuzz runs with 100_000 max rejections
#
# In this example, we only use the match-test flag, but any supported match
# flags can be used.

# First we define our default profile
[profile.default.fuzz]
runs = 250 # 250 runs by default for the default profile

[profile.default.fuzz.low]
# Any test that matches the provided regex uses this subprofile
match-test = "testFuzzLow.*"
runs = 50

[profile.default.fuzz.high]
match-test = "testFuzzHigh.*"
runs = 500

# Now we define our CI profile
[profile.ci.fuzz]
runs = 1000

[profile.ci.fuzz.low]
match-test = "testFuzzLow.*"
runs = 500

[profile.ci.fuzz.high]
match-test = "testFuzzHigh.*"
runs = 5000
max-global-rejects = 100_000

# EXTENSIONS
# You can imagine this extending to e.g. solidity configurations too when a
# [solidity] table is added, such as shown below:

# We define a lite mode to keep the optimizer off to speed up dev/testing.
# Since there's no `lite` fuzz config, it uses the default profile's settings.
[profile.lite.solidity]
optimizer = false

# In our default solidity profile we apply 10M optimizer runs.
[profile.default.solidity]
optimizer = true
optimizer-runs = 10_000_000

# But we have one really big contract, so we use 1 optimizer run to minimize
# its size.
[profile.default.solidity.size]
optimizer = true
optimizer-runs = 1
match-contract = "MyBigContract"

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions