-
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
feat(forge script
): preview, batch, and execute Gnosis Safe transactions (ape-safe)
#1232
Comments
Can you expand on |
I think
|
Thanks for bump—yes, |
Is there a standard for that we can use? @gakonst mentioned Gnosis Safe, but I wonder if |
Is there interest in supporting this feature? I think it's a natural extension to scripting and would help teams avoid manual Gnosis Transaction Builder inputs or relying on another tech stack (e.g. python with ape-safe) for setting up MS transactions. An initial version could be similar to the first iteration of CREATE2, hardcode the MultiSend contract from Gnosis and use their format for encoding transactions. The user would provide their safe address and a API call could be sent to the Gnosis Transaction Service to initiate the transaction. API could mirror broadcasting with something like I looked through the codebase a bit to see where it could naturally fit in, but I don't have a strong grasp of the existing scripting architecture. I am willing to work on this, but am not very experienced with Rust so I would need some pointers. |
Yep I think that's valuable. Motivation makes sense. Can you give a description of how you imagine the API working and then how a list of transactions would get encoded internally into a gnosis safe TX? |
+1 on this, would really improve the developers' experience of interacting with Safe, without going out of Solidity code, which is a quite typical use case. Regarding the API, maybe following the approach of other tx sender types like |
Here's a potential UX: First, we add logic to scripting so that it can take the gas estimates and split all broadcasted txs into chunks of 30M (or whatever the gas limit is per-chain). This has two use cases: (1) batching multi-sig txs into a single tx, and (2) batching flashbots txs into a single bundle. For (2), we use that logic when the flashbots RPC (or For (1), if you pass
For dry runs, you might not have an RPC provided which means you can't infer that it's a multisig tx that needs bundling, so perhaps there's also a |
APIAn alternative to passing the safe address to A rough example would be:
Transaction EncodingThe MultiSend contract expects the transaction batch to be encoded as follows:
Gnosis has implemented logic to batch transactions in this format in ethers-multisend, which should provide a good starting point. Transaction SubmissionThe Safe Transaction Service allows Safe owners and their delegates to initiate transactions, which will appear in Safe app for signers to execute. In this context, |
Something important to have is the possibility of creating the Safe tx with DELEGATE_CALL (1) We use this pattern for clarify-sake of what is executed: doing 1 single tx calling 1 single function in a contract, via DELEGATECALL. |
@eboadom what are all the ways that you configure the safe tx beyond the |
Currently, we are not doing this programmatically, basically because we can achieve something similar with a "push pattern" of permissions to a smart contract, instead of DELEGATECALL. |
I've been thinking about a more minimalist way to implement this. The current Solidity API with Taking a step back, I believe there are two separate features here.
If you do both of those, then you could batch broadcasted transactions and submit to the the service. For 1, a CLI flag In regards to @eboadom's comments on the Operation type (CALL vs. DELEGATECALL), ape-safe assumes all the batched transactions are CALLs and then makes the single txn from the Safe contract to the MultiSend contract a DELEGATECALL (https://github.com/banteg/ape-safe/blob/66ab8fefbb0edd4a892e18b26a92fedc4f65ed84/ape_safe.py#L117). If more nuanced control is needed, a cheatcode could be added to make individual batched calls into delegate calls (e.g. For 2, I'm less sure of a good UX. One option could be to update the Regardless of the CLI flag used, a new function in Looking for feedback on this framing and implementation approach. |
I see your point. Having a "mode" for So this might be simpler than we thought:
|
converting to a single safe TX is likely undesirable. This is a power user feature, and we should have a relatively powerful interface to it. We want to switch back and forth within the context of a script. E.g. broadcast all unpermissioned actions, and queue any permissioned actions for execution in a later batch. We also don't want to assume that only 1 batch will be produced in the script, so we need a batch identifier. the right api is probably more like:
Scripts that produce safe batches should sign and submit to the API, and print a link to the relevant safe UI after execution |
This might sound super scary, but it may be worth rewriting the script feature in the coming months (cc @joshieDo FYI/Not a Request) if we're thinking about how to support use cases like that. Need to noodle on it. Might be a nice X-mas refactoring project for me... |
@prestwich If non-permissioned and permissioned actions are interleaved during script execution, but actual execution is not interleaved and happens a completely different times, it will be impossible to test the script. That seems like a source of hard to understand errors. At least in my case, the following would be enough and I'm guessing quicker to be ready for use:
Delegatecalls can be manually initiated from the script. |
This really depends on what is being done, and users sophisticated enough to design a system that does that should be allowed to manage their own rough edges. It's not an average use case, so we should allow it but without guard rails |
@Oighty @gakonst Currently going through deployments using Gnosis Safe and stumbled upon this issue. Still trying to figure out the best way to glue everything together, and where to jump from forge scripts into typescript and the Gnosis Safe Transactions API. Anything new since this thread has been updated? I see #4878 was added, but looks like it requires building the typed data manually in scripts as opposed to just broadcasting? Let me know if I am misunderstanding. Another observation regarding the above APIs. If it will be possible to have multiple batches I suggest having each batch have an uint256 batchId = vm.startBatch();
// do some stuff
vm.stopBatch(batchId); // sanity check that we are starting/stopping the correct batch
// customize how batch is sent
address safe;
uint256 GNOSIS_SAFE; // some constant for the batch "method" or "mode"
vm.broadcastBatch(batchId, safe, GNOSIS_SAFE); Some more thoughts:
|
I don't believe a built-in solution is currently being worked on.
I generally agree with this, especially in the context of ERC-4337 and future contract wallet designs. I think it might make sense to have the routing of transactions be handled based on wallet config. More specifically, be able to "send" transactions to RPCs (e.g. traditional mempool) or alternative destinations (e.g. Safe Transaction Service or AA Alt Mempools). The options here depend on the wallet type. Therefore, it may make sense to add a Once you have the above, transactions batches could be defined in a script via something like the API you referenced. The type of "batch" is dependent on the destination and what it supports. Some chains support sending batches of txns to RPCs. STS supports MultiSend type batches. |
Hi guys, just stumbled upon this need and wanted to offer my 2c on how I resolved it in case it is helpful to anyone else running into this use case. The motivation was to generate and test a gnosis safe bundle for an existing multisig on mainnet. We could then submit the bundle using
|
@junhohong yep, that's the approach I ended up pursuing in lieu of native support for this. With #4878 , you can send payloads to be signed from the Solidity script via FFI. @ind-igo and I built out a library to do this called forge-safe. It also interacts with the safe-transaction-service API via Surl. I have a minor update to push that allows you to get values back from simulated calls and use them in the scripts. |
Just a heads up, I recently submitted a PR to do some refactoring of the https://github.com/ind-igo/forge-safe library to utilize the new improvements to wallet UX and Haven't tested it with hardware wallets though, not sure if |
Curious if the new |
forge script
): preview, batch, and execute Gnosis Safe transactions (ape-safe)
I've used forge-safe in the olympus-v3 repo (via the
Under the current setup with |
Component
Forge
Describe the feature you would like
Description:
My favorite tool from the Brownie/Vyper ecosystem is ape-safe. It lets you:
Now that Foundry is adding support for a local node and deploy scripts, it would be useful to have similar functionality out of the box.
Example:
I'm not sure what this looks like practically yet, but it might just be an executable Solidity script (transcribing the ape-safe Python example):
Potential use-cases:
Some potential applications:
Additional context
No response
The text was updated successfully, but these errors were encountered: