Bringing CREATE2 out of the EVM

Quai Network utilizes a sharded address space, meaning that only certain address are able to successfully send funds within each blockchain. This is done so that transaction validation is easily enforceable cross-chain. The set of address prefixes currently occupies a byte prefix for each blockchain in the network; in the future as the network grows the amount of addresses included in this list will increase.

Example Addresses:

  • Prime: 0x00 87245518127A1e11fCDBD54b285BCb4173df8C
  • Cyprus: 0x11 5046125D6Ba88C1FBcbE7203Ef663e37F08870
  • Cyprus One: 0x15 58F443A1bE597021fDa16C38c4AA126Fc569c3

The sharded address space has downstream effects on deploying contracts since contracts can only be considered valid in a shard if deployed to a specific prefix. Essentially contracts will need to “grind” a valid address. Traditionally there have been several uses cases for grinding/knowing contract addresses such as sending data to a predefined contract address before deployment.

The EVM employs a particularly useful opcode called CREATE2 which you can read more about here: EIP-1014: Skinny CREATE2. The CREATE2 opcode allows data to be sent to addresses that may not exist on chain yet through the EVM. CREATE2 addresses are derived by keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:] instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.

Bringing CREATE2 out of the EVM

In the case of Quai Network, since all contracts are required to be “grinded” to some extent it is necessary to utilize a CREATE2 like system on traditional contract deployment. This change will happen in the CreateAddress method. Essentially CreateAddress will function in the same way CREATE2 current does with the CreateAddress function on contract deployment taking in a uint64 salt. The salt must be specified as part of the transaction and for transactions that do not deploy contracts (simple transfers / contract interactions) it may serve as extra data.

What does this mean for CREATE2?
Since CreateAddress is functioning in a similar way to CREATE2, CREATE2 can be modified to solely be the EVM mechanism for deploying a contract.

What other benefits does the salt field provide?
By including the salt field, users who want a predefined address for their contract will no longer need to rely on a deploy. In EVM chains today it is typical to use deployer contracts that do not have predetermined addresses in order to create a contract with a known address. These deployer addresses can lead to bloat of the state tree.

3 Likes

Just for sake of clarification, the CreateAddress method is a protocol level method used for creating any kind of address (contract, simple account, etc.) correct?

What are the ramifications of removing the CREATE2 opcode from the EVM? Would it create functionality gaps for smart contract developers, or would they be filled by the new CreateAddress method?

Does adding the salt field to CreateAddress lead to additional state always being included in common transactions that would also eventually lead to bloat of the state tree?

1 Like

I don’t think we should add an 8-byte salt field to every transaction because 99% of transactions won’t use it, so it’s just bloat data. We should create a separate DeployTx type that has a salt field for Create2. If users want to use an internal transaction to create a contract (instead of the recommended DeployTx), they will have to use the legacy Create, and therefore they will have to grind out the proper contract address in the data field. Because the DeployTx type cannot be an ETX, a cross-chain contract deployment will always have to use the legacy Create (by grinding an integer at the end of the data field).

1 Like

That’s a really good point. I’m open to the DeployTx type being used for contract deployment with the salt. Would there need to be a guard on CreateAddress being called for a contract from a non DeployTx?

1 Like