foundry-rs / foundry-rs/foundry

Support custom backends in forge crate

Open
#9,262 1 comment 2 reactions 0 assignees View on GitHub
A-forge-builder A-internals T-feature T-post-V1
Dominant language
Rust
Stars
10.6k
Forks
2.6k
Avg merge
16h 38m
Merged PRs (30d)
511

Description

### Component

Forge

### Describe the feature you would like

## ❓ What are we doing?
We are building tooling that gives smart contract developers ways to create and verify zk-proofs in Solidity. We are utilizing revm with custom revm inspectors. We want to make it easy for developers to test their smart contracts using `forge`.

## The problem
We have a few inspectors that are necessary for the vlayer contracts to work. There's currently no easy way to run forge with with custom revm inspectors.

What we had to do was copy a bunch of code to replace backend in test executor with our custom backend with custom revm inspector.

Unfortinately, it's very deep in the call tree with nested builders, which made it necessary for us to copy a lot of very slightly modified `forge` code.
```
main
TestArgs::run()
TestArgs::execute_tests()
multi_runner = MultiRunnerBuilder::build()
TestArgs::run_tests(multi_runner, ...)
multi_runner.test()
for each contract:
multi_runner.run_test_suite()
executor = ExecutorBuilder::build()
runner = ContractRunner(executor, ...)
runner.run_tests()
for each test:
runner.run_unit_test()
executor.call()
... more calls inside executor...
executor.call_with_env()
We need to patch this
-----> Create backend with inspector
backend.call()
```

This makes it hard for us to keep it up to date with the current `foundry` codebase.

Another big issue is the fact that there're a lot of large files in the `/bin` dir, with makes it impossible to import them in any other crate.

## Can it be improved?
Yes, we believe so! And we think that it would be useful for other developers, if the `forge` crate was more modular and easy to use.

But talking solely about our use case, here's a minimal set of changes that would make our life much easier:

- Move (ideally all files from) `/bin/cmd` to `/src/cmd`
- Create `Executor` and `ExecutorBuilder` traits
- Accept `dyn ExecutorBuilder` in `TestArgs::execute_tests` and pass it down the tree
- `ExecutorBuilder::build()` would return `Box`
- ContractRunner would also keep `Box`

This way, we'd only need to reimplement `call_with_env` in the executor.

We will be happy to discuss this proposal and prepare the pull request!

### Additional context

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.