-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Forge Extensions #6509
Comments
related: #706 |
this would impact a lot of forge and would need more consideration. for example, fuzzing could randomly hit an extension address, potentially triggering the extension. there are 2 camps here, one that says we should automatically remove these from the fuzzer, and others who say we should still include them since any address is an attack vector not sure which i buy into more, but something to think about. generally, it makes sense to have pluggable precompiles as they fill a gap cli plugins couldn't in terms of wasm for post-compilation etc etc, i think we're better off having a cargo-like plugin ecosystem for non-evm things (compilers, static analyzers etc) rather than having hooks that call out to wasm |
Fully agree - but this has been talked about literally for over a year and no progress has been made! Really this issue is just to get the ball rolling on what it could actually look like and actually begin the conversation around all the edge cases. I do think this would be a major upgrade, if only for the differential fuzzing aspect (and have gotten multiple requests for extensions not just for differentials) |
Jumping in here to advocate for a few things:
Lastly wanted to share that I implemented similar foundry style scripting for my EVMts project. For context EVMts is a JavaScript library that takes very strong inspiration from foundry and essentially tries to bring foundry to the browser and node. It includes a VM inspired by anvil and a programming model inspired by foundry scripting. Here is how EVMts works for this. It's very similar to the python proposal:
|
I'm super happy to see some activity on better support for extensions. We'd love an official extensions system to tap into for Sphinx. I agree with @roninjin10 that JS support would be very nice. We use JS internally, so support for that would help us adopt this system much faster. However, we would probably migrate to any official extension system even if it required the use of a new language. Regarding the long-term scope for extensions, we would love to see hooks into the compilation process and especially into the transaction execution process. We would like to implement our custom execution strategy to replace the existing broadcast process and enable scripts to be executed natively within Foundry via our smart contract wallet. It would be awesome if this could be done in a generalized way, so anyone could inject extensions to modify the way scripts are executed. Some interesting examples might be:
|
I'd like create3 support to be built-in too. There are some highly optimized libraries now available for this. |
Supportive of adding extensions to Foundry, tracking It will require more discussion and specs before a start can be made. Personally I think having WASM based extensions is the preferable solution. It would be great if all of you can share your latest thoughts on the topic in the |
Component
Forge
Describe the feature you would like
Rational
vm.ffi
is an unsafe security hole, bad UX, and slow. Differential testing is too slow to be reasonable. Huff compilation is annoying.Scope
Initial scope should be EVM specific replacement/alternative to
vm.ffi
. Longer term, once the initial wasm runtime works well in an EVM context, there may be other places that make sense to allow plugins to tap into (compilation, post-test results, etc).Design Choices
There are two paths this design could take shape (there are more but these are most realistic):
Each have their pros and cons.
WASM based extensions are the "easiest" for plugin/extension developers - they don't have to implement an RPC server. Users can just write a snippet of code in their language of choice and ship it as either a standalone, shareable repo or even ship it inside their foundry-based project. This path likely leads to fragmentation, experimentation, but ultimately more developers making better use of foundry.
RPC based extensions are more flexible than WASM based extensions because there is no compilation to WASM (neither at the script or interpreter level). There is more overhead on the developers here, to where there is a centralizing and stabilizing force of extensions (think VSCode extensions - most people don't write custom extensions).
WASM path
Use wasmer wasm runtime at the core. Ship with pyodide by default to allow python to be ran. If we want to support javascript (I am not inclined to include this), we could ship with javy to compile JS to WASM on the fly and allow javascript to be ran.
I lean towards only supporting python extensions natively, and all others must be compiled to WASM by the user. I imagine python & rust will be most common languages for extensions to be built in.
WASM EVM interface
To satisfy the replacement of
vm.ffi
for most use cases, I suggest treating each extensions similarly to how we treatvm
, i.e. as a contract. A sketch of the full implementation:foundry.toml
have anextensions
configuration that points to wasm files. i.e.extensions = [ { name: "my_extension", path: "./my_local_extension.wasm", abi: "my_extension_abi.json"}]
. Extensions must be uniquely named and the path must be provided*(in theory, we could allow for global extensions in~/.foundry
). The path could potentially be something like{ style: "git", url: "https://github.com/...", wasm: "path/in/repo"}
in the future, and could be managed by git submodules akin to libraries.getExtension(string memory name) returns (address)
. Extensions are assigned an address by the contract runner, and upon callinggetExtension
, an address is returned allowing the user to interact with the extension via a normal contract callcall_extension
would determine the function in the extension to call and decode the input using the abi provided in the foundry.toml and call the function via the WASM runtimePython Example:
Eventually, we could expand this and define specific interfaces for non-evm based calls for compilation & post-test extensions (although arguably, an RPC-based system likely makes more sense for this kind of extension).
RPC based
Technically, this is sort of possible today with the introduction of
vm.rpc
, so I wont go into much more detail. You can in theory define a contract like:A real version of this would likely clean up some of this, maybe automatically creating some of this based on an abi in
foundry.toml
.RPC based is more interesting for pre and post-compilation, and pre and post-test as those interfaces are much more strictly defined.
My personal preference is towards the WASM path, but it is a not insignificant amount of complexity. The RPC version pushes more complexity on to developers and I think will result in much less usage.
Additional context
This is a request for feedback - I don't claim that either of these are the best path but just paths I have considered
The text was updated successfully, but these errors were encountered: