foundry
foundry copied to clipboard
feat: `vm.mineSalt` cheat code
Component
Forge
Describe the feature you would like
It's common to want to deploy with vanity addresses, which can be done two ways:
- Mine a private key that results in a contract with the right vanity pattern when deployed with some nonce
- Mine a salt for create2 that results in a contract with the right vanity pattern
Right now with approach 2 it's easy to mine a 4 character salt in a solidity script with a simple for loop, however you run out of gas (exceeds the u64 limit) if you try e.g. 8 characters. A cheat code for approach 1 isn't in consideration here since you'd need to fund the address mid-script and that feels clunky.
While of course you can do all the mining outside of the script, for short vanity addresses it's convenient to do this in the script, and without needing to rely on ffi or worry about the gas limit.
Proposed UX:
// Mine a salt for the given initcode hash and deployer that matches the provided
// pattern, specified as "0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", with the
// X's replaced by the desired pattern, (initcodeHash, deployer, pattern, caseSensitive) => (salt, contractAddress)
function mineSalt(bytes32 initcodeHash, address deployer, string calldata pattern, bool exact) external returns (bytes32 salt, address contractAddress)
Above, the user provides:
- The standard initcode hash and deployer address used for create2 address computation
- The pattern to match, using the syntax that profanity's
--matchingflag uses - A boolean to indicate if the match must be exact (case-sensitive)
And it returns the computed salt and the resulting address.
Additional context
No response
I would like to work on this one please.
Just a question, what would this cheat add from cast wallet vanity ?
Right now cast wallet vanity is for vanity EOAs, or for contracts deployed with CREATE (contracts created with CREATE are a function of deployer address and nonce). cast currently has no create2 helper, but it should (contracts created with CREATE2 are a function of the contract bytecode, deployer address, and a salt).
So this issue is separate from cast and would allow for mining the salt create2 contracts directly in a forge script file. I've personally wanted this for a little while, and have seen others request something similar in the foundry telegram.
To your point, we could add this directly to cast and then use ffi to access in a script, but personally I prefer a dedicated cheatcode (and eventually cast support also) because ffi can be dangerous since it executes arbitrary commands.
@onbjerg @mattsse let me know if you have any thoughts/objections here 🙂
I see your point, and didn't knew that cast wallet vanity was computing the contract address with CREATE.
Maybe we could add a cast wallet vanity2 or something, and then make the mineSalt cheatcode to avoid using ffi which is totally understandable, what do you think ?
Also, if we add the mineSalt cheatcode, maybe it should also be done for vanity with CREATE (not 2).
I think cast wallet vanity --create2 <initcodeHash> <deployer> <pattern> <case-sensitive>, and prints the salt and resulting contract address, could be a good syntax. That way it matches the cheat code, and both can use the same underlying rust method.
I have a slight preference of this being implemented in cast and then writing a simple solidity library that wraps cast with ffi instead of adding an additional cheatcode here
Just curious as to why you prefer a wrapper method that uses ffi? IMO a cheatcode is preferable for common actions like this to avoid introducing the security risks of ffi.
Assuming the wrapper method would be part of forge-std, I believe it would also be the first method in forge-std that uses ffi which i dont love for the same reason.
What about adding a feature to manually choose which directory has the right to run ffi to mitigate security issues ? I don't know what's the wish of the others from the team but maybe we shouldn't create a new cheatcode if it's not really necessary, but I agree that it would be better
I have a slight preference of this being implemented in
castand then writing a simple solidity library that wrapscastwithffiinstead of adding an additional cheatcode here
+1, that's the most straightforward solution
+1, that's the most straightforward solution
Happy to concede and go with that approach, but do want to understand why it's preferable given https://github.com/foundry-rs/foundry/issues/2359#issuecomment-1194767655 😅
Both the cast command and cheatcode should be able to use the same underlying method + not needing ffi seems like a big positive IMO
Another idea here if people don't like the idea of a vm.mineSalt cheatcode is vm.stopMeteringGas() and vm.resumeMeteringGas()` cheatcodes. That way you can then do gas-intensive things like mine a salt in solidity without burning through the gas limit. This would still be slower to execute than a cheatcode due to the added EVM overhead, but is another option to consider (not sure what other use cases there would be for these cheatcodes)
IMO a cheatcode is preferable for common actions like this to avoid introducing the security risks of ffi.
Strongly agree here! Would be nice to avoid having to ffi unless absolutely needed. Is there a lot of overhead involved with adding as a cheatcode if the code is already there for cast?
Another idea here if people don't like the idea of a vm.mineSalt cheatcode is vm.stopMeteringGas() and vm.resumeMeteringGas() cheatcodes
I really like this idea and I think it would be a valuable addition to Foundry for scripting. There are plenty of use cases where "slower execution, but we can keep our dev environment simple and all in Solidity" is a good tradeoff.
I will say that mining salts is an extremely common use case, so a rust-based cheat code specifically for it would be nice, as would a cast command. But I think the ability to stop/start gas metering is broadly useful as well. I guess what I'm saying is, I want both 😅
@mds1 It is a lot more complex to do vm.stopMeteringGas/vm.resumeMeteringGas especially since code inside those blocks may still affect state that affects overall gas consumption (sload/sstore etc.)
People are already doing this wiht FFI at this point FWIW e.g. https://github.com/antoncoding/grappa/blob/master/script/Deploy.sol#L70-L98
Let's do a cheatcode, the gas metering stuff seems like a big pain.
@mattsse Mind reopening this? We now have create2 support in cast, but don't actually have a forge cheatcode yet
Just curious as to why you prefer a wrapper method that uses ffi? IMO a cheatcode is preferable for common actions like this to avoid introducing the security risks of ffi.
Assuming the wrapper method would be part of forge-std, I believe it would also be the first method in forge-std that uses ffi which i dont love for the same reason.
On Mon, Jul 25, 2022 at 9:16 AM Mark Tyneway @.***> wrote:
I have a slight preference of this being implemented in cast and then writing a simple solidity library that wraps cast with ffi instead of adding an additional cheatcode here
— Reply to this email directly, view it on GitHub https://github.com/foundry-rs/foundry/issues/2359#issuecomment-1194305284, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEC6NVFMZSUWY5TMCJDJVBTVV24V5ANCNFSM532UEIXQ . You are receiving this because you authored the thread.Message ID: @.***>
Cheatcode :+1:
I think
cast wallet vanity --create2 <initcodeHash> <deployer> <pattern> <case-sensitive>, and prints the salt and resulting contract address, could be a good syntax. That way it matches the cheat code, and both can use the same underlying rust method.
This
Another script to mine salts by calling cast create2 over ffi: https://github.com/karmacoma-eth/foundry-playground/blob/main/script/MineSaltScript.sol
It feels a little odd to call cast over ffi and to parse the string output, I would much rather use a cheatcode
Another script to mine salts by calling
cast create2over ffi: https://github.com/karmacoma-eth/foundry-playground/blob/main/script/MineSaltScript.solIt feels a little odd to call cast over ffi and to parse the string output, I would much rather use a cheatcode
When I wanted to implement the cheatcode, I was limited by a circular dependency issue. Can eventually give it another go.