foundry icon indicating copy to clipboard operation
foundry copied to clipboard

feat: `vm.mineSalt` cheat code

Open mds1 opened this issue 3 years ago • 12 comments
trafficstars

Component

Forge

Describe the feature you would like

It's common to want to deploy with vanity addresses, which can be done two ways:

  1. Mine a private key that results in a contract with the right vanity pattern when deployed with some nonce
  2. 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 --matching flag 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

mds1 avatar Jul 18 '22 01:07 mds1

I would like to work on this one please. Just a question, what would this cheat add from cast wallet vanity ?

iFrostizz avatar Jul 20 '22 05:07 iFrostizz

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 🙂

mds1 avatar Jul 20 '22 05:07 mds1

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).

iFrostizz avatar Jul 20 '22 05:07 iFrostizz

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.

mds1 avatar Jul 20 '22 05:07 mds1

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

tynes avatar Jul 25 '22 16:07 tynes

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.

mds1 avatar Jul 25 '22 23:07 mds1

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

iFrostizz avatar Jul 26 '22 07:07 iFrostizz

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

+1, that's the most straightforward solution

mattsse avatar Jul 28 '22 12:07 mattsse

+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

mds1 avatar Jul 28 '22 15:07 mds1

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)

mds1 avatar Aug 03 '22 21:08 mds1

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 😅

apbendi avatar Aug 03 '22 21:08 apbendi

@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.)

onbjerg avatar Aug 04 '22 15:08 onbjerg

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.

gakonst avatar Aug 11 '22 16:08 gakonst

@mattsse Mind reopening this? We now have create2 support in cast, but don't actually have a forge cheatcode yet

mds1 avatar Sep 24 '22 14:09 mds1

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: @.***>

mds1 avatar Oct 11 '22 07:10 mds1

Cheatcode :+1:

gakonst avatar Oct 11 '22 18:10 gakonst

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

sambacha avatar Oct 14 '22 20:10 sambacha

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

0xkarmacoma avatar Jan 21 '23 00:01 0xkarmacoma

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

When I wanted to implement the cheatcode, I was limited by a circular dependency issue. Can eventually give it another go.

iFrostizz avatar Jan 22 '23 23:01 iFrostizz