ZeframLou / create3-factory

270 stars 36 forks source link

Suggestion to ease deployment to other chains #4

Open dvush opened 1 year ago

dvush commented 1 year ago

I like the idea of having contracts deployed on the same address for every chain but there is a problem with deployment for every eth compatible chain.

Is it possible to sign and publish deployment txs for every known chain id? There can be a problem with gas prices but it should be possible to sign tx for different gas prices (i.e by doubling from small to high value).

Then everyone who wants to have this thing on their chain can fund this deployment.

CodeSandwich commented 1 year ago

This would be awesome, but it's impossible, either the private key is published and anybody can waste its 0 nonce on an unimportant transaction, or all possible future transactions are predicted and pre-signed.

The IMO right solution is to use one of the deterministic CREATE2 deployers, e.g. the widely used https://github.com/Arachnid/deterministic-deployment-proxy, this way anybody can trustlessly do the deployment on any chain they want, if only it has the deterministic deployer in place.

CodeSandwich commented 1 year ago

The deterministically deployed CREATE3Factory is 0x6aa3d87e99286946161dca02b97c5806fc5ed46f, regardless of the chain or who deployed it (e.g. https://etherscan.io/address/0x6aa3d87e99286946161dca02b97c5806fc5ed46f).

Anybody can deploy it on any chain for everybody to use, as long as the Arachnoid's deterministic deployment proxy is already deployed (https://github.com/Arachnid/deterministic-deployment-proxy, always at 0x4e59b44847b379578588920ca78fbf26c0b4956c). To do the deployment, just reuse the deployment transaction's data and use it to call the deterministic deployment proxy (e.g. from https://etherscan.io/tx/0x0fd91d6ee78abcd6cdf93a84ad509e80ac3bac94398994be0ea2dc501b79197f). For clarity, it uses nonce 0. It's exactly the same creation code as ZaframLou used in the official deployments.

For reference, here's a shell script function doing the deployment using Foundry: https://github.com/radicle-dev/drips-contracts/blob/232029aa1ded48751b01709311987535ee6d3a97/scripts/deploy.sh#L40. You should never build Create3Factory from source, because the bytecode will be different if you don't use exactly the same Solidity version and configuration, and you'll end up deploying under a different address.

@ZeframLou WDYT about making this way of deploying the "official" one? You would get rid of the burden of being the holder of the single private key guaranteeing the consistency of the CREATE3Factory address. If you lose it, accidentally waste its nonce 0 on any chain or have it stolen, the whole promise of consistency will collapse. You also won't be bugged to make new deployments on different chains, which will also accelerate the adoption of your contract.

wei3erHase commented 1 year ago

@CodeSandwich issit not in zkSync? 😭

CodeSandwich commented 1 year ago

I don't know, probably not. You can deploy it yourself if you need it (of course if zkSync is EVM-compatible enough).

tab00 commented 1 year ago

The deterministically deployed CREATE3Factory is 0x6aa3d87e99286946161dca02b97c5806fc5ed46f

It has only been deployed on Ethereum mainnet, goerli and sepolia.

Do you think it'd be OK to instead use the CREATE3 factory offered by https://github.com/lifinance/create3-factory which is already deployed on many blockchains?

CodeSandwich commented 1 year ago

Of course it would be OK, use whatever you want :laughing: LiFi implemented a practically identical CREATE3Factory as ZeframLou. They seem to use a private key for their CREATE3Factory deployments, so if you ever want to deploy on a different chain, you'll need to ask them to do that for you. This probably won't be a problem though, because they've already deployed on so many chains.

tab00 commented 1 year ago

LiFi implemented a practically identical CREATE3Factory as ZeframLou

Yes, it's a fork but "updated to use legacy (non EIP-1559) transactions due to the fact that some chains that LIFI supports do not support EIP-1559".

if you ever want to deploy on a different chain, you'll need to ask them to do that for you

That's a good point, for future-proofing. So with https://github.com/Arachnid/deterministic-deployment-proxy, if we deployed the CREATE2 factory ourself on a future desired blockchain, would it have the same address as the others (0x4e59b44847b379578588920ca78fbf26c0b4956c)?

Then if we deploy the CREATE3 factory contract ourself using the CREATE2 factory at 0x4e59b44847b379578588920ca78fbf26c0b4956c, it should have address 0x6aa3d87e99286946161dca02b97c5806fc5ed46f like the other CREATE3 factory contracts, right?

CodeSandwich commented 1 year ago

IIUC LiFi only changed the deployment script to use the --legacy flag, but it doesn't affect the deployment addresses, it's still the hash of the deployer's address and their nonce.

...right?

You're right, Arachnid's CREATE2 factory is guaranteed to always be under the same address (if its deployment transaction can be executed, it may be tricky due to gas cost being hardcoded, read the repo readme). The deployment of CREATE3Factory is then guaranteed to land on the same address, because it only depends on the salt (let's agree to use 0) and the CREATE3Factory bytecode (that's why we always must use exactly the same bytecode down to a single byte).

tab00 commented 1 year ago

Do you mean salt instead of nonce?

I see a salt of 0 is used to deploy CREATE3 factory in https://github.com/radicle-dev/drips-contracts/blob/232029aa1ded48751b01709311987535ee6d3a97/scripts/deploy.sh#L83-L84

CodeSandwich commented 1 year ago

Yes, salt, sorry. Fixed the comment.

tab00 commented 1 year ago

Arachnid's CREATE2 factory is guaranteed to always be under the same address (if its deployment transaction can be executed

But how about if the nonce of 0x3fAB184622Dc19b6109349B94811493BF2a45362 changes before we deploy the CREATE2 factory on a new blockchain? Would that cause the CREATE2 factory contract to have a different address due to a non-0 nonce at the time that we submit the deploy transaction?

Would we have to hope that the holder of the private key of 0x3fAB184622Dc19b6109349B94811493BF2a45362 does not make any transactions in that account on our desired blockchain before we deploy the CREATE2 factory?

CodeSandwich commented 1 year ago

Nobody can build any transaction for 0x3fAB184622Dc19b6109349B94811493BF2a45362 other than the one deploying deterministic deployer. If you look at the deployment transaction details:

blockHash            0xdaa690a16bc4a2bf2ff8955ff1cf3bc2155bc9c53f5731b6f8706fdc2b33b82c
blockNumber          10670819
from                 0x3fAB184622Dc19b6109349B94811493BF2a45362
gas                  100000
gasPrice             100000000000
hash                 0xeddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26
input                0x604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3
nonce                0
r                    0x2222222222222222222222222222222222222222222222222222222222222222
s                    0x2222222222222222222222222222222222222222222222222222222222222222
to                   
transactionIndex     42
v                    27
value                0

you can see that the signature (r, s, v) is very weird. The trick is that the transaction was manually constructed, an arbitrary signature has been attached to it, and then the signer's address was recovered from that signature, which happened to be 0x3fAB184622Dc19b6109349B94811493BF2a45362. Nobody knows what's the private key of that address, so nobody can use it to sign any other transaction, we only know about a single transaction and a single signature that match this address.

I don't know where I read the full explanation of this trick, Arachnid's repository could include it.

dvush commented 1 year ago

This would be awesome, but it's impossible, either the private key is published and anybody can waste its 0 nonce on an unimportant transaction, or all possible future transactions are predicted and pre-signed.

The IMO right solution is to use one of the deterministic CREATE2 deployers, e.g. the widely used https://github.com/Arachnid/deterministic-deployment-proxy, this way anybody can trustlessly do the deployment on any chain they want, if only it has the deterministic deployer in place.

I think there is a misunderstanding about what this issue it about.

  1. Its not impossible to do, the recipe for doing that is described in the first message. You just have to presign deployment transaction for all chain id and different gas prices (e.g. different powers of 2). Are there any arguments that this does not work?
  2. Using some other deterministic deployment contract to deploy this one to the same address its not a solution. The problem of having to seed deterministic deployer on the same address on different chains is still needs to be solved by someone (in this case by the deployers of Arachnid/deterministic-deployment-proxy )

For example, I would like to be able to deploy this to the same address on the private test chains.

tab00 commented 1 year ago

So can we have some reusable deployment transaction bytecode that will give us a CREATE3 factory on any blockchain at the same address every time?

SKYBITDev3 commented 1 year ago

Hi @tab00 , @CodeSandwich , @dvush. I cover a lot of your concerns in my repository SKYBIT Keyless Deployment. You really should check it out as I think I have what you're looking for.

I'd suggest against using Nick's / Zoltu's factories as they are insecure. I explain it in the README.

tab00 commented 1 year ago

Thanks, it looks like just what I need. I'll definitely check it out in depth, it's a lot to digest.

zxstim commented 4 months ago

The deterministically deployed CREATE3Factory is 0x6aa3d87e99286946161dca02b97c5806fc5ed46f, regardless of the chain or who deployed it (e.g. https://etherscan.io/address/0x6aa3d87e99286946161dca02b97c5806fc5ed46f).

Anybody can deploy it on any chain for everybody to use, as long as the Arachnoid's deterministic deployment proxy is already deployed (https://github.com/Arachnid/deterministic-deployment-proxy, always at 0x4e59b44847b379578588920ca78fbf26c0b4956c). To do the deployment, just reuse the deployment transaction's data and use it to call the deterministic deployment proxy (e.g. from https://etherscan.io/tx/0x0fd91d6ee78abcd6cdf93a84ad509e80ac3bac94398994be0ea2dc501b79197f). For clarity, it uses nonce 0. It's exactly the same creation code as ZaframLou used in the official deployments.

For reference, here's a shell script function doing the deployment using Foundry: https://github.com/radicle-dev/drips-contracts/blob/232029aa1ded48751b01709311987535ee6d3a97/scripts/deploy.sh#L40. You should never build Create3Factory from source, because the bytecode will be different if you don't use exactly the same Solidity version and configuration, and you'll end up deploying under a different address.

@ZeframLou WDYT about making this way of deploying the "official" one? You would get rid of the burden of being the holder of the single private key guaranteeing the consistency of the CREATE3Factory address. If you lose it, accidentally waste its nonce 0 on any chain or have it stolen, the whole promise of consistency will collapse. You also won't be bugged to make new deployments on different chains, which will also accelerate the adoption of your contract.

Thanks. Super useful deployment script. I deployed on Kaia mainnet and testnet and the address came out same as yours.

SKYBITDev3 commented 4 months ago

I provide a hardhat script that allows you to deploy a CREATE3 factory via Arachnid's CREATE2 factory at https://github.com/SKYBITDev3/SKYBIT-Keyless-Deployment/blob/main/scripts/deployViaDDP-Create3Factory.js