[ERC1014] コントラクトのデプロイ先アドレスを事前に予測する仕組みを理解しよう！

# はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、`CREATE2`という新しいオペコードを導入し、コントラクトのデプロイ先アドレスを事前に予測可能にする仕組みを提案している**ERC1014**についてまとめていきます！

:::note info
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-1014

他にも様々なEIPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

:::note info
この提案の概要は以下を参考にしてください。
:::

https://github.com/cardene777/smart-contract/blob/develop/docs/create2.md

# 仕様

`CREATE2` は、EVM（Ethereum Virtual Machine）における新しいオペコードで、`0xf5` 番に割り当てられています。
スタック引数として以下の4つを取ります。

* `endowment`
    * 初期残高（送金するETHの量）
* `memory_start`
    * メモリの開始位置（initコードの位置）
* `memory_length`
    * メモリの長さ（initコードの長さ）
* `salt`
    * 任意の32バイトの値（アドレスの決定に使われる）

`CREATE2` の挙動は、既存の `CREATE`（0xf0）とほぼ同じですが、コントラクトのアドレス生成方法が異なります。

アドレスの計算には以下の式が使われます。

```
keccak256( 0xff ++ address ++ salt ++ keccak256(init_code) )[12:]
```

* `0xff` は1バイトの固定値
* `address` はコントラクトを生成するアドレス（20バイト）
* `salt` はスタック上にある32バイトの値
* `init_code` は新しいコントラクトの初期化コード（デプロイ時に実行されるコード）

このハッシュ値の最後の20バイトが、新しく生成されるコントラクトのアドレスとなります。
前処理データの長さは常に85バイトで固定されます。

また、ガス消費に関しては `CREATE` と同じですが、`init_code` に対する `keccak256` のハッシュ処理のために追加で次のようなガスコストがかかります。

```
GSHA3WORD × ceil(len(init_code) / 32)
```

この追加コストは、メモリ拡張や `CreateGas` と同時に差し引かれます。
つまり、アドレスの評価や `init_code` の実行前に処理されます。

# 動機

`CREATE2` の導入は、以下のようなユースケースを実現・支援するためです。

* ステートチャネル（state channel）のように、オンチェーンにまだ存在していないコントラクトと確実にインタラクションする必要がある場合
* コントラクトがまだデプロイされていない段階でも、将来そのコードがデプロイされたときにどのアドレスになるかを事前に確定できること

これにより、オフチェーン上での事前合意や、カウンターファクチュアル（仮想的）なインタラクションが可能になります。
実際にコードがデプロイされる前から、そのアドレスに対して安全に取引や署名ができるという特性は、Layer2やスマートウォレット、Meta-transaction などにおいて非常に有効です。

# 補足

## アドレスの設計方針

`CREATE2`で使用されるアドレス生成方式は、以下の理由で設計されています。

### アドレスの衝突防止

通常の `keccak256(rlp([sender, nonce]))` によるアドレス生成方式とは異なり、先頭に `0xff` バイトを含めることで、アドレスの計算結果が従来方式と重複しないように設計されています。
`0xff` で始まるRLPエンコードは事実上現実的に生成不可能なサイズ（ペタバイト級）になるため、安全に区別できます。

### ハッシュ対象の固定長化

ハッシュ前のデータ（preimage）は常に85バイトとなるよう設計されており、最適化やセキュリティに寄与します。

## ガスコストに関する設計

`CREATE2`では、アドレス生成時に `init_code` に対して `keccak256` ハッシュを計算するため、DoS（サービス拒否攻撃）を防ぐ目的で、コードサイズに応じた追加コストが課されます。

このコストは、SHA3（`keccak256`）オペコードと同じ「32バイトあたりのコスト（GSHA3WORD）」を適用し、メモリ拡張ガスと同様に処理の最初で差し引かれます。

# 説明

## init_codeについての明確化

`init_code` とは、コントラクトをデプロイする際に最初に実行されるコードのことです。
このコードが出力するバイト列が、そのままコントラクトのランタイムコード（実行時コード）としてステートに保存されます。
Solidityなどの高級言語では、コンストラクタの処理に相当します。

## アドレス衝突時の動作

`CREATE2`によって、同じアドレスへのコントラクト再生成が可能となるケースがありますが、**EIP684**により衝突時の仕様が明示されています。

:::note info
**EIP684**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/8678b581b7d4444eda7a

* 対象アドレスに既にコードやノンスが存在している場合、`CREATE2`は即座に失敗します。
* この失敗は、`init_code` の最初のバイトが無効なオペコードであるかのような動作になります。
* これはEthereumの創世ブロック（genesis）から一貫して適用されます。

## EIP161との関係

**EIP161**では、コントラクト生成時にアカウントのnonceが即座にインクリメントされます。
つまり、`CREATE`や`CREATE2`でコントラクトを作成した直後は、そのアドレスのnonceが非ゼロになるため、同一トランザクション内での再生成は常に失敗します。

さらに、`SELFDESTRUCT`（コントラクトの自己削除）を呼び出しても、nonceやコードがすぐにクリアされるわけではないため、同一トランザクション内での破壊と再生成は不可能です。

## アドレス生成の具体例

以下の例では、異なる入力に対して`CREATE2`がどのようなアドレスを返すかが示されています。

* **Example 0**

  ```
  address: 0x000...000  
  salt:   0x000...000  
  init_code: 0x00  
  → 結果: 0x4D1A...BF38
  ```

* **Example 1**

  ```
  address: 0xdeadbeef...  
  salt:   0x000...000  
  init_code: 0x00  
  → 結果: 0xB928...FDA3
  ```

* **Example 2**

  ```
  address: 0xdeadbeef...  
  salt:   0x000...feed...  
  init_code: 0x00  
  → 結果: 0xD041...9833
  ```

* **Example 3**

  ```
  address: 0x000...000  
  salt:   0x000...000  
  init_code: 0xdeadbeef  
  → 結果: 0x70f2...cb5e
  ```

* **Example 4**

  ```
  address: 0x000...deadbeef  
  salt:   0x000...cafebabe  
  init_code: 0xdeadbeef  
  → 結果: 0x60f3...8AC7
  ```

* **Example 5**

  ```
  address: 0x000...deadbeef  
  salt:   0x000...cafebabe  
  init_code: 64バイト以上のdeadbeefの繰り返し  
  → 結果: 0x1d8b...854C
  ```

* **Example 6**

  ```
  address: 0x000...000  
  salt:   0x000...000  
  init_code: 空（0x）  
  → 結果: 0xE33C...d9e0
  ```

これらの例からも、同じ`init_code`でも、`salt`や`デプロイ元アドレス`が異なると、アドレスも変化することが明確にわかります。
これは、`CREATE2`が意図的に衝突を避けつつ、事前にアドレスを確定できる設計であることを示しています。

# 引用

Vitalik Buterin (@vbuterin), "EIP-1014: Skinny CREATE2," Ethereum Improvement Proposals, no. 1014, April 2018. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1014.

# 最後に

今回は「`CREATE2`という新しいオペコードを導入し、コントラクトのデプロイ先アドレスを事前に予測可能にする仕組みを提案している**ERC1014**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4