Skip to content

feat: vm.mineSalt cheat code #2359

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
mds1 opened this issue Jul 18, 2022 · 24 comments · Fixed by #2467
Closed

feat: vm.mineSalt cheat code #2359

mds1 opened this issue Jul 18, 2022 · 24 comments · Fixed by #2467
Labels
A-cheatcodes Area: cheatcodes C-forge Command: forge Cmd-forge-script Command: forge script Cmd-forge-test Command: forge test T-feature Type: feature

Comments

@mds1
Copy link
Collaborator

mds1 commented Jul 18, 2022

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 mds1 added the T-feature Type: feature label Jul 18, 2022
@gakonst gakonst added this to Foundry Jul 18, 2022
@gakonst gakonst moved this to Todo in Foundry Jul 18, 2022
@onbjerg onbjerg added Cmd-forge-test Command: forge test C-forge Command: forge A-cheatcodes Area: cheatcodes Cmd-forge-script Command: forge script labels Jul 19, 2022
@iFrostizz
Copy link
Contributor

iFrostizz commented Jul 20, 2022

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

@mds1
Copy link
Collaborator Author

mds1 commented Jul 20, 2022

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 🙂

@iFrostizz
Copy link
Contributor

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

@mds1
Copy link
Collaborator Author

mds1 commented Jul 20, 2022

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.

@tynes
Copy link
Contributor

tynes commented Jul 25, 2022

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

@mds1
Copy link
Collaborator Author

mds1 commented Jul 25, 2022

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.

@iFrostizz
Copy link
Contributor

iFrostizz commented Jul 26, 2022

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

@mattsse
Copy link
Member

mattsse commented Jul 28, 2022

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

@mds1
Copy link
Collaborator Author

mds1 commented Jul 28, 2022

+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 #2359 (comment) 😅

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
Copy link
Collaborator Author

mds1 commented Aug 3, 2022

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)

@apbendi
Copy link

apbendi commented Aug 3, 2022

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 😅

@onbjerg
Copy link
Collaborator

onbjerg commented Aug 4, 2022

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

@gakonst
Copy link
Member

gakonst commented Aug 11, 2022

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.

Repository owner moved this from In Progress to Done in Foundry Sep 24, 2022
@mds1
Copy link
Collaborator Author

mds1 commented Sep 24, 2022

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

@mattsse mattsse reopened this Sep 24, 2022
@mds1
Copy link
Collaborator Author

mds1 commented Oct 11, 2022 via email

@gakonst
Copy link
Member

gakonst commented Oct 11, 2022

Cheatcode 👍

@sambacha
Copy link
Contributor

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

@0xkarmacoma
Copy link
Contributor

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

@iFrostizz
Copy link
Contributor

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.

@zerosnacks
Copy link
Member

zerosnacks commented Aug 1, 2024

Since the ticket was raised most developers use https://github.com/0age/create2crunch for finding efficient salts, often hiring a GPU cluster in the cloud. Having this be part of running the script flow as a cheatcode seems a bit redundant to me.

@zerosnacks zerosnacks removed this from the v1.0.0 milestone Aug 1, 2024
@0xkarmacoma
Copy link
Contributor

Since the ticket was raised most developers use https://github.com/0age/create2crunch for finding efficient salts, often hiring a GPU cluster in the cloud. Having this be part of the running the script flow as a cheatcode seems a bit redundant to me.

using create2crunch is much more involved though. It's great when you want to mine 14 zeroes for Seaport, but sometimes all you need is a cute selector with a given prefix. Having a convenient option to do that locally is nice without having to go rent a GPU

@zerosnacks
Copy link
Member

I see - that makes sense, I was only considering the leading 0 case

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

Hi @iFrostizz, would you be interested in picking this ticket back up?

@iFrostizz
Copy link
Contributor

iFrostizz commented Aug 1, 2024

Hi @zerosnacks , I am not anymore, will unassign me ! Not sure about your philosophy around cheatcode, imo they should be added sparingly, only when working around it is not possible. ffi would have worked here, and it seems that mineSalt is not something that many people use. For instance, if you want to mine a lot of zeros, then I would definitely mine it out of the script. You don't want to let it compute for hours just to have a network issue at the end while not logging the private key.

@iFrostizz iFrostizz removed their assignment Aug 1, 2024
@jenpaff jenpaff moved this from Done to Todo in Foundry Sep 30, 2024
@DaniPopes
Copy link
Member

Closing given the niche use case and the already available ffi options. I don't think separate cheatcode(s) + potential forge-std integration is worth it, or even preferable.

@github-project-automation github-project-automation bot moved this from Todo to Done in Foundry Nov 30, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-cheatcodes Area: cheatcodes C-forge Command: forge Cmd-forge-script Command: forge script Cmd-forge-test Command: forge test T-feature Type: feature
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.