

This is the third and final article in a series about deterministic deployments. In the first two entries (1, 2) we covered a lot of ground: managed private keys, Nick's method, pre-signed transactions, CREATE2 factories, and CREATE3. In this entry we'll explore some additional approaches, including a couple of relatively recent and quite interesting ones.
All the methods we've discussed so far are available to anyone who wants to use them. For completeness, though, we should mention another way to get a contract at a given address: include it at the protocol level. That is, the contract exists at that address simply because the rules of the chain say it does. Contracts included this way are usually called preinstalls.1
This is exactly what OP Stack chains do: the four CREATE2 factories we discussed in the previous article, along with many other contracts, are available without having been deployed through a transaction.
Preinstalls make a chain more "batteries included", but they can also serve as a useful last resort. Consider a contract that was deployed many times using Nick's method but that can't be deployed in some new chain because the gas limit of the transaction is too tight. In this case, the chain could decide to add the contract as a preinstall in a network upgrade. It's not a method you would choose first, but it's good to know the option exists.
RIPs are Rollup Improvement Proposals, a mechanism for standardizing behavior across different rollups. RIP-7740 simply proposes that all rollups preinstall a set of CREATE2 factories at their usual addresses, so that anyone can count on their availability. The specified set is precisely the four contracts from our previous article: Arachnid's Deterministic Deployment Proxy, create2deployer, Safe Singleton Factory, and CreateX.
EIP-7997 proposes adding a CREATE2 factory as a predeploy2 to the Ethereum L1 and, by extension, to any EVM-compatible chain that wants to stay in sync with the protocol. This would be a minimal factory with a behavior similar to that of Arachnid's Deterministic Deployment Proxy.3
One interesting property of this approach is that a predeploy doesn't have an ECDSA private key associated with it, making it quantum-resistant. The CREATE2 factories we discussed before don't offer this guarantee: if ECDSA is ever broken, a future attacker could derive the deployer key and potentially front-run any deployment on new chains with other code. Whether this is a realistic concern is debatable (it requires both ECDSA being broken and that new EVM chains are still being created) but it's a clean property to have regardless.
As its name indicates, ERC-7955 is an ERC rather than an EIP 4, meaning it doesn't require any changes to the protocol. Instead, it proposes a standardized mechanism to perform a deterministic deployment, and uses it to bootstrap a CREATE2 factory.
The proposed mechanism assumes that EIP-7702 (Set EOA Account Code) is available in the target chain. We are not going to explain EIP-7702 here, but let's quickly recap two aspects that matter for the ERC:
EIP-7702 lets an EOA "transform" itself into a contract. More precisely: any transaction sent to an EIP-7702-transformed EOA results in a delegate call to some specified address.
For an EOA to delegate its execution, it doesn't need to send a transaction itself. It only needs to sign an authorization, and that authorization needs to be included in an EIP-7702 transaction, which in turn can be sent from any address.
With that in mind, here's how ERC-7955 works:

A well-known private key, corresponding to ERC7955EOA in the diagram, is used to sign an authorization that delegates to SomeCreate2Factory. Neither the address nor the code of this factory matter, as long as it can be used to deploy contracts with CREATE2.
Once the EOA is delegated, a transaction is sent to it (from any account) to deploy another factory: ERC7955Factory, the one we actually want to have at a deterministic address. The key insight is this: when the delegated EOA is called and it delegate-calls SomeCreate2Factory, the “sender” parameter used to compute the deployment address is ERC7955EOA, not the one from SomeCreate2Factory (as it would happen in a non-delegate call). That's why the identity of the factory doesn't matter: the resulting address is determined by the well-known EOA's address, the salt, and the init code, all of which are fixed in advance.
One way I like to think about this method is that we're executing the CREATE2 opcode from an EOA, something that was impossible before EIP-7702. This combines the address stability of a managed key with CREATE2's nonce-independence.
A big upside of ERC-7955 is that there's no need to keep a private key safe; in fact, the key is intentionally made public. Anyone who wants to deploy the factory in a new chain can use it to sign the required EIP-7702 authorization. The main downside is that this method requires EIP-7702, a relatively recent feature, to be available.
There's also a subtler downside. Since the private key is well-known, anyone could sign a different authorization with the same nonce and front-run5 the delegation, temporarily blocking the deployment. That said, this isn't a fatal flaw: a new authorization can always be signed with a higher nonce, and we can keep trying until one goes through. And, in the face of a stubborn attacker, we can always use a private mempool to guarantee the authorization is included.
We've covered a broad range of techniques, from the simplest ones to the most recent:
Managed private keys, pre-signed transactions, and Nick's method, which are based on normal deployment transactions and have different trade-offs around key custody, replay protection, and permissionlessness.
CREATE2-based approaches like CREATE2 factories and CREATE3. Given the wide availability of CREATE2 factories, these should be the first option to consider for anyone wanting to deploy a contract in a deterministic way.
The methods discussed in this article: preinstall-based ideas or the clever ERC-7955.
It's worth pointing out that both ERC-7955 and EIP-7997 were proposed less than a year ago. It wouldn't be surprising if new approaches keep emerging.
Thanks for reading! If you'd like to be notified when new articles are published, you can subscribe to the blog.
For a detailed explanation on the difference between precompiles, preinstalls, predeploys, and system contracts, check my answer here.
↩In this context, there isn't much difference between preinstall and predeploy. See the link in the previous footnote for more details.
↩Both use the first 32 bytes of the calldata as the CREATE2 salt, and the rest as the init code. But they have (at least) two small differences: 1) The EIP-7997 factory returns 32 bytes, while Arachnid's returns 20, and 2) The EIP-7997 code forwards the revert reason if the contract creation fails, while Arachnid's doesn't.
↩EIP stands for Ethereum Improvement Proposal, while ERC means Ethereum Request for Comments.
↩Since the contents of the mempool are public, an attacker could see a transaction that includes an authorization signed by a well-known private key, use that key to sign a different authorization with the same nonce, and pay a higher gas price to incentivize the block builder to include it first. Once included, the original transaction becomes invalid, because it contains an authorization with a nonce that has already been used.
↩This is the third and final article in a series about deterministic deployments. In the first two entries (1, 2) we covered a lot of ground: managed private keys, Nick's method, pre-signed transactions, CREATE2 factories, and CREATE3. In this entry we'll explore some additional approaches, including a couple of relatively recent and quite interesting ones.
All the methods we've discussed so far are available to anyone who wants to use them. For completeness, though, we should mention another way to get a contract at a given address: include it at the protocol level. That is, the contract exists at that address simply because the rules of the chain say it does. Contracts included this way are usually called preinstalls.1
This is exactly what OP Stack chains do: the four CREATE2 factories we discussed in the previous article, along with many other contracts, are available without having been deployed through a transaction.
Preinstalls make a chain more "batteries included", but they can also serve as a useful last resort. Consider a contract that was deployed many times using Nick's method but that can't be deployed in some new chain because the gas limit of the transaction is too tight. In this case, the chain could decide to add the contract as a preinstall in a network upgrade. It's not a method you would choose first, but it's good to know the option exists.
RIPs are Rollup Improvement Proposals, a mechanism for standardizing behavior across different rollups. RIP-7740 simply proposes that all rollups preinstall a set of CREATE2 factories at their usual addresses, so that anyone can count on their availability. The specified set is precisely the four contracts from our previous article: Arachnid's Deterministic Deployment Proxy, create2deployer, Safe Singleton Factory, and CreateX.
EIP-7997 proposes adding a CREATE2 factory as a predeploy2 to the Ethereum L1 and, by extension, to any EVM-compatible chain that wants to stay in sync with the protocol. This would be a minimal factory with a behavior similar to that of Arachnid's Deterministic Deployment Proxy.3
One interesting property of this approach is that a predeploy doesn't have an ECDSA private key associated with it, making it quantum-resistant. The CREATE2 factories we discussed before don't offer this guarantee: if ECDSA is ever broken, a future attacker could derive the deployer key and potentially front-run any deployment on new chains with other code. Whether this is a realistic concern is debatable (it requires both ECDSA being broken and that new EVM chains are still being created) but it's a clean property to have regardless.
As its name indicates, ERC-7955 is an ERC rather than an EIP 4, meaning it doesn't require any changes to the protocol. Instead, it proposes a standardized mechanism to perform a deterministic deployment, and uses it to bootstrap a CREATE2 factory.
The proposed mechanism assumes that EIP-7702 (Set EOA Account Code) is available in the target chain. We are not going to explain EIP-7702 here, but let's quickly recap two aspects that matter for the ERC:
EIP-7702 lets an EOA "transform" itself into a contract. More precisely: any transaction sent to an EIP-7702-transformed EOA results in a delegate call to some specified address.
For an EOA to delegate its execution, it doesn't need to send a transaction itself. It only needs to sign an authorization, and that authorization needs to be included in an EIP-7702 transaction, which in turn can be sent from any address.
With that in mind, here's how ERC-7955 works:

A well-known private key, corresponding to ERC7955EOA in the diagram, is used to sign an authorization that delegates to SomeCreate2Factory. Neither the address nor the code of this factory matter, as long as it can be used to deploy contracts with CREATE2.
Once the EOA is delegated, a transaction is sent to it (from any account) to deploy another factory: ERC7955Factory, the one we actually want to have at a deterministic address. The key insight is this: when the delegated EOA is called and it delegate-calls SomeCreate2Factory, the “sender” parameter used to compute the deployment address is ERC7955EOA, not the one from SomeCreate2Factory (as it would happen in a non-delegate call). That's why the identity of the factory doesn't matter: the resulting address is determined by the well-known EOA's address, the salt, and the init code, all of which are fixed in advance.
One way I like to think about this method is that we're executing the CREATE2 opcode from an EOA, something that was impossible before EIP-7702. This combines the address stability of a managed key with CREATE2's nonce-independence.
A big upside of ERC-7955 is that there's no need to keep a private key safe; in fact, the key is intentionally made public. Anyone who wants to deploy the factory in a new chain can use it to sign the required EIP-7702 authorization. The main downside is that this method requires EIP-7702, a relatively recent feature, to be available.
There's also a subtler downside. Since the private key is well-known, anyone could sign a different authorization with the same nonce and front-run5 the delegation, temporarily blocking the deployment. That said, this isn't a fatal flaw: a new authorization can always be signed with a higher nonce, and we can keep trying until one goes through. And, in the face of a stubborn attacker, we can always use a private mempool to guarantee the authorization is included.
We've covered a broad range of techniques, from the simplest ones to the most recent:
Managed private keys, pre-signed transactions, and Nick's method, which are based on normal deployment transactions and have different trade-offs around key custody, replay protection, and permissionlessness.
CREATE2-based approaches like CREATE2 factories and CREATE3. Given the wide availability of CREATE2 factories, these should be the first option to consider for anyone wanting to deploy a contract in a deterministic way.
The methods discussed in this article: preinstall-based ideas or the clever ERC-7955.
It's worth pointing out that both ERC-7955 and EIP-7997 were proposed less than a year ago. It wouldn't be surprising if new approaches keep emerging.
Thanks for reading! If you'd like to be notified when new articles are published, you can subscribe to the blog.
For a detailed explanation on the difference between precompiles, preinstalls, predeploys, and system contracts, check my answer here.
↩In this context, there isn't much difference between preinstall and predeploy. See the link in the previous footnote for more details.
↩Both use the first 32 bytes of the calldata as the CREATE2 salt, and the rest as the init code. But they have (at least) two small differences: 1) The EIP-7997 factory returns 32 bytes, while Arachnid's returns 20, and 2) The EIP-7997 code forwards the revert reason if the contract creation fails, while Arachnid's doesn't.
↩EIP stands for Ethereum Improvement Proposal, while ERC means Ethereum Request for Comments.
↩Since the contents of the mempool are public, an attacker could see a transaction that includes an authorization signed by a well-known private key, use that key to sign a different authorization with the same nonce, and pay a higher gas price to incentivize the block builder to include it first. Once included, the original transaction becomes invalid, because it contains an authorization with a nonce that has already been used.
↩<100 subscribers
<100 subscribers
Share Dialog
Share Dialog
Franco Victorio
Franco Victorio
No comments yet