HIP-329: Support CREATE2 opcode Source

AuthorMichael Tinker
Discussions-Tohttps://github.com/hashgraph/hedera-improvement-proposal/discussions/328
StatusFinal
Needs Council ApprovalYes
Review period endsTue, 01 Feb 2022 07:00:00 +0000
TypeStandards Track
CategoryService
Created2022-01-14
Updated2022-04-26

Abstract

EIP-1014 introduced the CREATE2 opcode to let a contract be deployed to a predictable address on the Ethereum blockchain.

Because each Hedera entity must have a unique 0.0.X id, and the Solidity address of a Hedera contract is currently determined by its 0.0.X id, there has not, historically, been a natural way to implement CREATE2 on our ledger.

But after HIP-32, there is now a mechanism in the code that provides a level of indirection between a ByteString “alias” and a 0.0.X id. We propose in this HIP to implement CREATE2 by re-using the alias mechanism to link the deterministic address specified in EIP-1014 to a new contract’s 0.0.X id.

To externalize this 0.0.X-to-address link to mirror nodes in the record stream, we propose to re-use the “internal” transaction records introduced in HIP-206, only adding a new bytes evm_address field to the record. To simplify client calls to contracts created via CREATE2, we propose to extend the Hedera API (HAPI) protobufs so that this evm_address identifier can be used anywhere HAPI accepts a ContractID.

Motivation

Standard implementations of a distributed exchange (DEX), for example, make heavy use of the CREATE2 opcode. This opcode can also improve user onboarding flows in dApps. We want to let such applications to be deployed on Hedera.

Rationale

The business value of this HIP is self-evident, so the only decision points are in the changes to Services code and protobuf messages. Our reasoning is that:

  1. Re-use of the alias mechanism reduces risk and complexity in the codebase.
  2. Externalizing created 0.0.X-to-address links via a new evm_address field in a child record follows the same pattern used in auto-account creation.
  3. Although the GetBySolidityIDQuery could be re-enabled, and clients required to use it
    to look up the ContractID of an EVM address, this poorly named query is not free—and some clients may want to pre-compute the CREATE2 address and use it directly.

User stories

  • As a Hedera DEX operator, I want to re-use standard Solidity contracts that use the CREATE2 opcode.

Specification

  • Implement the CREATE2 EVM opcode 0xF5 in Services by linking the EIP-1014 address to the new contract’s underlying 0.0.X id as an alias, and updating the EVM address lookup to be alias-aware.
  • When the ADDRESS EVM opcode is executed in the context of a contract with an EIP-1014 address, preferentially return the EIP-1014 address instead of the “mirror” 0x0000...<X> address that derives from the contract’s 0.0.X id.
  • Externalize this evm_address-to-0.0.X link via new ContractCreate child records which will now be created for every internal EVM creation (whether processed with CREATE or CREATE2).
  • (HAPI) Include a new bytes evm_address field in the TransactionRecord message, to be populated in these child transaction records.
  • (HAPI) Deprecate the createdContractIDs field in the ContractFunctionResult message, since this information will now be duplicated by the new child transactions.
  • (HAPI) When the 0.0.<alias> form of an AccountID is used in a CryptoTransferTransactionBody, respect use of an evm_address for the alias portion; thus allowing a HAPI client to do a native transfer of assets to a contract known only by its CREATE2 address.
  • (HAPI) Extend the ContractID protobuf message as below, so that an evm_address identifier can be used anywhere that HAPI accepts a ContractID. ``` message ContractID { /**
    • The shard number (nonnegative) */ int64 shardNum = 1;

    /**

    • The realm number (nonnegative) */ int64 realmNum = 2;

    oneof contract { /**
    * A nonnegative number unique within a given shard and realm */ int64 contractNum = 3;

      /**  
      * The 20-byte EVM address of the contract to call. 
      * 
      * Every contract has an EVM address determined by its <tt>shard.realm.num</tt> id.
      * This address is as follows:
      *   <ol>
      *     <li>The first 4 bytes are the big-endian representation of the shard.</li>
      *     <li>The next 8 bytes are the big-endian representation of the realm.</li>
      *     <li>The final 8 bytes are the big-endian representation of the number.</li>
      *   </ol>  
      * 
      * Contracts created via CREATE2 have an <b>additional, primary address</b> that is 
      * derived from the <a href="https://eips.ethereum.org/EIPS/eip-1014">EIP-1014</a> 
      * specification, and does not have a simple relation to a <tt>shard.realm.num</tt> id. 
      * 
      * (Please do note that CREATE2 contracts can also be referenced by the three-part 
      * EVM address described above.)
      */
      bytes evm_address = 4;   } } ```
    

Backwards Compatibility

No existing contract should be affected by this HIP—unless it was failing due to use of CREATE2, in which case it should become functional.

Security Implications

The Ethereum community and others have now demonstrated patterns that allow safe use of CREATE2. As long as users follow the patterns in these contracts, there should not be security implications.

How to Teach This

“Implement EIP-1014 on Hedera to allow creating contracts at pre-determined addresses.”

Reference Implementation

The user-facing changes to HAPI have been discussed in this PR.

Rejected Ideas

In principle, it may be possible to make CREATE2 addresses globally unique across all shards. But the extreme complexity of this task did not seem justified by the value provided.

Open Issues

No blocking issues are known at this time.

References

Copyright/license

This document is licensed under the Apache License, Version 2.0 – see LICENSE or (https://www.apache.org/licenses/LICENSE-2.0)

Citation

Please cite this document as: