Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document invariant testing + patterns #497

Closed
gakonst opened this issue Aug 3, 2022 · 16 comments · Fixed by #760
Closed

Document invariant testing + patterns #497

gakonst opened this issue Aug 3, 2022 · 16 comments · Fixed by #760
Labels
A-forge Area: forge T-new Type: new docs

Comments

@gakonst
Copy link
Member

gakonst commented Aug 3, 2022

foundry-rs/foundry#1572

https://github.com/maple-labs/revenue-distribution-token/tree/e0eca03c2ff05c36000a097de678543d7234f7cc/contracts/test

document simple invariant breaking, the actor model from Maple's RDT, usage of targetContract(s) etc

@onbjerg onbjerg moved this to Todo in Foundry Book Aug 3, 2022
@onbjerg onbjerg added A-forge Area: forge T-new Type: new docs labels Aug 3, 2022
@Perelyn-sama
Copy link
Contributor

Getting this done.

@lucas-manuel
Copy link
Contributor

lucas-manuel commented Aug 8, 2022

Thoughts on patterns:

Open Invariant Testing

This testing pattern deploys all relevant contracts in the setUp function and exposes all the functions in these contracts to the fuzzer. This pattern must use revert_on_failure = false in the foundry.toml, since this pattern will make calls with unbounded values.

Pros Cons
- Checks all functions
- Unbounded params
- Single actor
- Reversions

Bounded Actor-Based Invariant Testing

This testing pattern deploys all relevant contracts in the setUp function and deploys wrapper contracts to call the functions on the contract. These contracts act as actors in a more realistic simulation of interactions against the desired contracts. These contracts can have relevant permissions and will perform calls with parameters bounded to reasonable values. This pattern must use revert_on_failure = true in the foundry.toml, since this pattern should expose any unexpected reversions over the course of the fuzzing campaign.

User contract reference.

To take it a step further, a contract can be used to dynamically deploy new actors during the fuzzing campaign and perform actions from these actors (example).

Another use case for this pattern is to create a contract that will call the vm.warp cheatcode at random intervals to simulate the passage of time and ensure that invariants are still held (example).

This pattern must add all non-wrapper contracts deployed in the setUp function into the excludeContracts array as to ensure that these contracts are only called through the wrapper contracts.

Pros Cons
- Many actors
- Can simulate passage of time
- Can expose unexpected reversions
- Potential human error in incorrect implementations of wrapper functions

Unbounded Actor-Based Invariant Testing

Similar pattern to above, except with unbounded parameters. This allows for the contract to be called without any artificially bounded parameters, potentially exposing previously unconceived vectors to break invariants. This pattern must use revert_on_failure = false in the foundry.toml, since this pattern will make calls with unbounded values.

Pros Cons
- Many actors
- Can simulate passage of time
- Unbounded parameters
- Reversions

@Perelyn-sama
Copy link
Contributor

Hey @lucas-manuel can we get examples of the first and last example too please, thanks

@lucas-manuel
Copy link
Contributor

Currently all the invariant examples we have are private, but here is an open source implementation of bounded actor-based invariant testing: https://github.com/maple-labs/revenue-distribution-token/blob/add-forge-invariants/contracts/test/Invariants.t.sol

@JacoboLansac
Copy link

When are Invariant tests expected to be released to the public? Looking forward to it. Thanks!

@gakonst
Copy link
Member Author

gakonst commented Oct 9, 2022

They are already released!

@JacoboLansac
Copy link

They are already released!

What!
According to the foundry book they are not yet supported. https://book.getfoundry.sh/forge/advanced-testing

Am I looking at the wrong version of the foundry book? Or, can I have a link to the documentation of invariant tests? Damn I'm excited!

@Perelyn-sama
Copy link
Contributor

https://github.com/foundry-rs/foundry/tree/master/testdata%2Ffuzz%2Finvariant

@JacoboLansac
Copy link

https://github.com/foundry-rs/foundry/tree/master/testdata%2Ffuzz%2Finvariant

And an example project where it is used?
Thank you very much!

@Perelyn-sama
Copy link
Contributor

Scroll up

@azflin
Copy link

azflin commented Jan 18, 2023

There is no official docs for this still?

@gakonst
Copy link
Member Author

gakonst commented Jan 19, 2023

Soon :) For now take a look at https://github.com/lucas-manuel/invariant-example and #760

@PaulRBerg
Copy link
Contributor

take a look at https://github.com/lucas-manuel/invariant-example and #760

Also maple-core-v2.

@github-project-automation github-project-automation bot moved this from Todo to Done in Foundry Book Feb 10, 2023
@JacoboLansac
Copy link

what is the best way of managing blockchain time in invariant tests?
So far I did a work around using a storage variable of the handler contract and a modifier that would warp time before each of the target functions, but I was wondering if there was a better way. Thanks

@aviggiano
Copy link

aviggiano commented May 9, 2023

What does dictionary_weight mean and how does it affect the fuzzer performance? I can't find any docs related to it.

@gakonst
Copy link
Member Author

gakonst commented May 10, 2023

Could you guys please open new issues about these questions, for us to document them in the book?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-forge Area: forge T-new Type: new docs
Projects
No open projects
Status: Done
Development

Successfully merging a pull request may close this issue.

8 participants