foundry
foundry copied to clipboard
`forge clone`: Clone verified contracts as foundry project
Component
Forge
Describe the feature you would like
Problem
Currently, foundry provides a feature that downloads the source code of contracts from Etherscan: cast etherscan-source. However, cast etherscan-source only dumps the sources of contract in the filesystem simply, without being able to compile.
This creates an obstacle on blockchain developers, who may want to re-compile the contracts of popular DApps, customize it, deploy in a local chain, write foundry tests/scripts with the contract, etc.
Proposal
We propose to add a new subcommand for forge: forge clone, which clones source code of a verified contract on Etherscan and creates a foundry project on local file system. The usage of the command is forge clone <address> <path/to/cloned/project>.
Our fork of foundry, EtherDebug/foundry, has already implement this feature. We encourage developers to try out this subcommand on our fork of foundry.
We welcome any comments and suggestions helping us improve this feature and contribute to a better smart contract development and debugging experience.
Downstream Application
Cloning the source code of contracts from Etherscan also enables multiple downstream usage, one of which is on-chain contract tweak feature that we introduce in our fork EtherDebug/foundry.
The on-chain contract tweak allows users to alter the code of an on-chain contract with its on-chain state preserved. This feature enables a very handy feature that developers can insert "printf" into on-chain contracts and replay transactions.
The first step of tweaking an on-chain contract is to clone the source code of an on-chain contract. So we presume introducing forge clone to foundry is a significant step forward.
This tweak feature has recently attracted much attention on Twitter. We would like to bring the discussion to a broader audience regarding upstreaming the forge clone and tweak features to the main foundry project.
Disclosure
@ZhangZhuoSJTU and me (@Troublor) are the authors of EtherDebug/foundry, which introduces the On-chain Contract Tweak features in foundry. Please take a look at our demo on Twitter.
Additional context
that's awesome, very supportive of this feature!
happy to start the integration of this!!
best way would probably a big PR for forge clone, then we can extract the required tweaks and apply them separately
The PR of forge clone is already on the way!
Hi @mattsse, I am wondering that, considering the merge of forge clone, could we discuss potential next steps for integrating the tweak feature?
If the current working directory is a foundry project created by forge clone, then the command forge replay is available to replay a historical transaction with the on-chain contract's code tweaked by the current project. Note that the cloned project "knows" which contract address it should tweak.
I believe this is very similar to vm.transact cheatcode?
what if generate a test that
- deploys the cloned contract to the onchain address
then you should be easily fork and transact via cheatcodes?
@mattsse, yes, it is a very good point. However, there are a few subtle nuances to consider (especially when we tweak the contracts and hence change the data in the creation Tx).
The most challenging issue concerns create2. Due to potential tweaks and modifications to the original code, the creation code might change, resulting in a target address that differs from the original one. In this context, a practical workaround would be to first execute a transaction to obtain the deployed code, and then forcibly assign this code to the original address. It's important to note that when replaying using tweaked contracts, we hope that these contracts occupy the same addresses (so that we do not need to change other contracts involved in the replayed Tx).
Moreover, this solution might not be sufficient. Some contracts include expressions like immutable X = address(this), meaning that if the target address (address(this)) changes (due to tweaks), the deployed code will not match the expected one. To address this, we may need to introduce an inspector to hook the behavior of the ADDRESS opcode during creation.
Additionally, there are several peripheral tasks, such as identifying the creation transaction and its corresponding block, and forking & adjusting the Tx position, which users might find cumbersome to handle themselves.
That is basically the main motivation of use to introduce an additional code module (but the current code organization may not be optimal and needs your advise).
Another challenge here is that, not all contracts are deployed by EoA, but rather by other (factory) contracts, e.g., Uniswap. In our implementation, we hook the actual creation call and do the aforementioned replacement.
By writing a test, I somewhat do not figure out an elegant approach to do this. Lol
Hi @mattsse,
I am wondering whether there is any update on the status of this issue? Any insights would be greatly appreciated.
Thanks!
Marking as resolved by https://github.com/foundry-rs/foundry/pull/7576 which adds forge clone