Skip to content
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

Add CREATE2 contract factory with support for meta transactions #1651

Closed
marekkirejczyk opened this issue Feb 26, 2019 · 5 comments
Closed
Labels
contracts Smart contract code. feature New contracts, functions, or helpers.

Comments

@marekkirejczyk
Copy link

🧐 Motivation
This is in connection to #1644. We would like to have a CREATE2 factory that supports meta-transactions. We expect that CREATE2 & meta-transaction will be a common combination.

I expect interface and implementation for the factory with and without meta-transaction to differ a lot.

📝 Details
Proposed interface:

contract Create2MetaTransactionFactory {

    /* Creates factory with fixed code */
    function constructor(bytes memory _contractCode) public;

    /* Deploys a contract, required salt and factory address to be signed by signer */
    function deployContract(address _signer, bytes32 _salt, bytes memory _signature) public;
    
    /* Gets an address before contract deployment */
    function computeContractAddress(bytes32 _salt, address _signer) public view 
        returns (address _contractAddress);
}

An example implementation is in universal login repository on ETHDenver hackathon branch.

Code created by @cwhinfrey as he was helping our team during the hacking time.

@nventuro
Copy link
Contributor

Hey there @marekkirejczyk, thanks for contributing to this discussion!

I've been taking a look at your proposed interface and have a couple questions: from what I can tell, the only difference between it and the one mentioned in #1644 is the presence of the signer argument (along with a valid signature for deployment), which is hashed together with the salt to produce the actual salt that is used for CREATE2. What is the purpose of this argument?

The only scenario that I can think of is a user that wants to reserve an address and make sure no other account will be able to deploy a contract there, even if the salt is leaked. Said scenario wouldn't make much sense at a first glance, since the bytecode of the deployed contract is known (worst case, the 'attacker' would've paid for our user's deployment), unless the contract has some sort of one-off initialization function (in the style of ZeppelinOS's Initializable) that is meant to be called right after contract creation.

In that case, I'd expect the actual flow to look like this: user calls contract A with salt, signature, and initialization data, which then deploys a new contract using the factory, and immediately initializes it with the provided data. This could, however, be simplified by including an optional data argument in your proposed deployContract function, which would conditionally call the created contract with this value (again, see how ZeppelinOS does this).

Please share your thoughts!

@cwhinfrey
Copy link
Contributor

@nventuro The purpose of including the signer when creating the actualSalt (salt passed into create2, open to different names for this) is exactly what you mentioned, contracts with one off initialize() functions.

We do need to either: 1) Prevent other accounts from deploying the contract by using the signer to calculate the salt or 2) use the initialization data when calculating the salt to ensure different initialization data can't be used.

The reason is that we don't want third parties to be able to deploy the contract and initialize it with different data than was intended. For example, there might be ETH sitting in the future address of a wallet contract that is initialized with an owner. We want to make sure a third party can't deploy the contract and set themselves as the owner. On top of that, the salt will always be leaked because deployments can be front run.

I like the second option listed above where the actualSalt is based on a user determined salt and the initialization data like this:

bytes32 actualSalt = keccak256(abi.encodePacked(salt, initData))

That way changing the initialization data will change the contract address. It's more flexible than the first option because any account can deploy the contract. I might have some time tonight to write up a quick gist of this.

@cwhinfrey
Copy link
Contributor

Haven't tested this but here's one way it could possibly look when computing the salt with the initialization data: https://gist.github.com/cwhinfrey/380d2d073b122f7903bd9acb060d470a
Create2FactroyBase is based on @stanislaw-glogowski's ContractCreator. The contracts could also be combined into a single contract instead of having a base contract. No signed message handling for meta-transactions needed because anyone can deploy the contract.

@nventuro
Copy link
Contributor

nventuro commented Feb 27, 2019

Thanks @cwhinfrey! That clarified a lot.

On top of that, the salt will always be leaked because deployments can be front run.

Wouldn't the signing of the message prevent front-running though?

I like both options you described, there's a flexibility trade-off: either only a single account does the deployment, with arbitrary initialization data (the actualSalt = hash(salt, signer) approach), or any arbitrary account does the deployment, with single pre-defined initialization data (the actualSalt = hash(salt, data) approach). We could of course have the salt include both signer and data, but I don't see much benefit in that.

None of the approaches strike me as objectively better than the other, I can think of scenarios in which they could all be useful. Perhaps we should support them both?

@nventuro nventuro added feature New contracts, functions, or helpers. contracts Smart contract code. labels Feb 27, 2019
@nventuro nventuro added this to the v2.3 milestone Feb 27, 2019
@frangio frangio removed this from the v2.3 milestone Apr 8, 2019
@frangio
Copy link
Contributor

frangio commented Aug 26, 2020

Fixed in #2013.

@frangio frangio closed this as completed Aug 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contracts Smart contract code. feature New contracts, functions, or helpers.
Projects
None yet
Development

No branches or pull requests

4 participants