[EIP3541] 0xEFで始まるコントラクトのデプロイを禁止する提案を理解しよう！

# はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

今回は、EVM Object Format（EOF）に準拠するコントラクトをデプロイ時に検証するため、`0xEF`バイトで始まる新コードのデプロイを禁止する提案している**EIP3541**についてまとめていきます！

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

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

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

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

# 概要

特定のバイト（`0xEF`）で始まる新しいコードのデプロイを禁止するという提案に関するものですが、既にアカウントのトライ（ブロックチェーンのデータ構造の一種）に存在する`0xEF`バイトで始まるコードは、この変更の影響を受けません。

### 新しいコードのデプロイ制限
この提案により、`0xEF`バイトで始まる新しいコードのブロックチェーンへのデプロイが禁止されます。

### 既存コードへの影響なし
しかし、この変更は既にブロックチェーン上に存在するコードには影響しません。
つまり、このルールの変更前に`0xEF`バイトで始まるコードとしてデプロイされていたものは引き続きそのまま機能します。
この規定により、既存のシステムやアプリケーションが不必要に影響を受けることがないように配慮されています。

### セマンティック（意味論的）な影響
「**セマンティックに影響を受けない**」というフレーズは、既存のコードの動作や意味がこの変更によって変わらないことを意味します。
つまり、既にデプロイされている機能やロジックには何の変更もないということです。

この提案は新しいルールを設定して、特定の形式の新しいコードのデプロイを禁止するものですが、既に存在するコードには何の影響もありません。
これにより、ブロックチェーンのセキュリティや整合性を向上させることができますが、過去にデプロイされたコードの動作には影響しません。

# 動機

EVM Object Format（EOF）という新しいイーサリアムのコントラクトフォーマットに関連した提案です。

:::note info
### EVM Object Format（EOF）
EVMはEthereum Virtual Machineの略で、イーサリアムのスマートコントラクトを実行するための仮想マシンです。
EOFは、このEVM上で動作するスマートコントラクトのための新しいフォーマットです。

従来のスマートコントラクトはバイナリ形式でコンパイルされ、そのままEVMにデプロイされますが、この方法ではコントラクトの内容が一見して理解しにくいという問題がありました。
EOFはこの問題に対処するために提案されたもので、スマートコントラクトをより構造化された形式で記述し、それをEVMが解釈しやすくすることを目指しています。

EOFの主な特徴は以下の通りです。

**構造化されたフォーマット**
コントラクトのコードとデータを明確に区別し、読みやすく管理しやすい形式で記述します。
これにより、開発者がコントラクトをより簡単に理解し、デバッグしやすくなります。

**検証と最適化の容易化**
EOF形式のコントラクトは、デプロイ前により厳密な検証が可能になります。
また、EVMにおける実行効率の最適化もしやすくなるため、トランザクションの実行コストが削減される可能性があります。

**バージョニングサポート**
EOFはバージョン情報を含むため、EVMやコントラクト自体の将来のアップグレードが容易になります。
これにより、イーサリアムプラットフォームの進化に伴って、スマートコントラクトをより柔軟に対応させることが可能です。

**セキュリティの向上**
EOF形式を採用することで、コードの構造が明確になり、潜在的なセキュリティリスクを事前に検出しやすくなります。
これは、スマートコントラクトの安全性を高める上で大きな利点となります。

EOFはイーサリアムのスマートコントラクトをより効率的に、かつ安全にデプロイ・実行するための新しいフォーマットです。
開発者にとってはコントラクトの開発が容易になり、ユーザーにとってはトランザクションのコストが削減される可能性があるというメリットがあります。
:::

### EOFコントラクトの検証
EOFに準拠するコントラクトは、デプロイ時に検証されます。
これは、ブロックチェーン上にデプロイされるすべてのEOFフォーマットのコントラクトが有効であることを保証するためです。

### 既存のコントラクトとの区別
既にデプロイされている（そして検証されていない）コントラクトがEOFフォーマットとして認識されないようにする必要があります。
これを達成するために、「**マジック**」と呼ばれる特定のバイトシーケンスを使用します。
このマジックは、EOFフォーマットを識別するための一意のマーカーで、既存のコントラクトには存在しないものを選択します。

### 検索スペースの制限
この新しいフォーマットの導入によって、既存のコントラクトをすべて調べる必要が生じないように、新しいフォーマットの開始バイト（マジックの最初のバイト）の使用を禁止します。
これにより、分析をフォーク前に存在するコントラクトに限定し、検索スペースの増大を防ぎます。

### 将来の柔軟性
もしEOF提案が将来的にデプロイされなかった場合、他の機能やバージョニングに依存する機能にマジックを使用することができます。
バージョニングが時代遅れになった場合、`0xEF`バイトで始まるコントラクトのデプロイを再び許可することで、この変更を簡単に元に戻すことが可能です。

この提案はEOFフォーマットに準拠する新しいコントラクトの検証プロセスを導入し、同時に既存のコントラクトとの互換性を保ちつつ、将来的な柔軟性も考慮しています。

# 仕様

イーサリアムのスマートコントラクトのデプロイメントに関わる技術的な変更について述べたものです。
特定のブロック番号（`HF_BLOCK`と呼ばれる）以降、新しいコントラクトを作成する時（`create`トランザクション、または`CREATE`、`CREATE2`命令を使用して）に、コントラクトのコードの最初のバイトが`0xEF`である場合、その操作は例外的に中断されます。

### initcodeの役割
`initcode`は、コントラクト作成時に実行されるコードを指します。
このコードは、`CREATE`や`CREATE2`命令を通じて、新しいコントラクトのコードを返します（`RETURN`命令を使用して）。
この返されたコードがアカウントに挿入され、コントラクトとして機能します。

### 0xEFオペコードの扱い
オペコード`0xEF`は現在、未定義の命令とされています。
つまり、この命令を実行するとスタック項目をポップ（取り除く）もプッシュ（追加）もせず、実行時に例外的な中断を引き起こします。
これにより、`0xEF`で始まる`initcode`や既にデプロイされたコードが実行されると、引き続き実行が中断されます。

### 例外的な中断の挙動
コードが`0xEF`で始まる場合の例外的な中断は、`initcode`の実行中に発生可能な他のどの例外的中断とも全く同じように振る舞います。
つまり、`CREATE`命令や`create`トランザクションが中断されると、その操作に提供された全ガス（実行に必要な手数料）が消費されます。

この変更は、セキュリティやプロトコルの整合性を保つために導入されることが多く、特定のオペコードの使用を制限することで、予期しない動作や悪意のある利用を防ぐことを目的としています。
また、開発者がコントラクトのコードをより慎重に設計し、未定義の命令を避けるよう促すことも意図しています。

# 補足

イーサリアムのスマートコントラクトで特定のバイト値（この場合は`0xEF`）を使用する背景と理由について説明しています。

### 0xEFバイトの選択
`0xEF`バイトは「**Executable Format（実行可能フォーマット）**」を連想させるため選ばれました。
これは、イーサリアムのスマートコントラクトや他の実行可能コードにおいて、ある種の標準や規約に従うことを示唆しています。

### 未割り当てオペコードの使用
スマートコントラクトで未割り当て（つまり、現在イーサリアムプロトコルにおいて特定の機能や動作が定義されていない）オペコードを使用することは、将来的にそのオペコードに機能が割り当てられた際にコントラクトの意味合いが変わるリスクがあると一般に理解されています。
そのため、未割り当てのオペコードである`0xEF`を使用することは、既に割り当てられているオペコード（例えば、`0xFD`（`REVERT`）、`0xFE`（`INVALID`）、`0xFF`（`SELFDESTRUCT`）など）を使用するよりも影響が少ないと考えられます。

### 既存コントラクトの分析
2021年5月の分析によると、約1,808,4433件のコントラクトが存在する中で、`0xEF`バイトで始まる既存のコントラクトは0件でした。
これに対し、`0xFD`、`0xFE`、`0xFF`で始まるコントラクトはそれぞれ1件、4件、12件存在していました。
この分析は、`0xEF`を使用することで既存のコントラクトに影響を与えずに新しい規則を導入できることを示しています。

ここでは、`0xEF`バイトを新しいスマートコントラクトの作成において特定の条件を満たすためのマーカーとして選択する理由を説明しています。
この選択は、既存のコントラクトに影響を与えず、未割り当てのオペコードを使用することのリスクを最小限に抑えることを目的としています。

# テスト

異なるコンテキスト（`create`トランザクション、`CREATE`命令、`CREATE2`命令）で実行されるテストケースに関するテストです。
これらのテストケースは、特定のバイト値（例えば`0xEF`や`0xFE`）で始まる新しいコントラクトのデプロイを試みるものです。
各ケースにおける「`Calldata`」は、トランザクションまたは命令によって渡されるデータを示しており、「**Expected resul**t」はそのテストケースの予想される結果を示しています。

- **`create`トランザクション**
    - アカウントコードがない状態で新しいコントラクトを作成する方法です。
- **`CREATE`命令**
    - 既存のアカウントコード（この例では`0x6000356000523660006000f0151560165760006000fd5b`）を持つコンテキストで新しいコントラクトを作成する方法です。
- **`CREATE2`命令**
    - 別の既存のアカウントコード（この例では`0x60003560005260003660006000f5151560185760006000fd5b`）を持つコンテキストで新しいコントラクトを作成する方法です。

各テストケースの結果は、新しいコントラクトのデプロイが成功したか、または特定の理由（この場合はコードの最初のバイトが`0xEF`である）で失敗したかを示します。

こちらが各テストケースとその予想される結果を表形式でまとめたものです。

| Case                  | Calldata            | Expected result                           |
|-----------------------|---------------------|-------------------------------------------|
| deploy one byte ef    | `0x60ef60005360016000f3` | new contract not deployed, transaction fails |
| deploy two bytes ef00 | `0x60ef60005360026000f3` | new contract not deployed, transaction fails |
| deploy three bytes ef0000 | `0x60ef60005360036000f3` | new contract not deployed, transaction fails |
| deploy 32 bytes ef00...00 | `0x60ef60005360206000f3` | new contract not deployed, transaction fails |
| deploy one byte fe    | `0x60fe60005360016000f3` | new contract deployed, transaction succeeds |

この表からわかる通り、`0xEF`で始まるバイト列を含む新しいコントラクトのデプロイは全て失敗すると予想されます。
これは、`0xEF`が特定のルールまたはプロトコルの変更によって「**使用禁止**」とされているためです。
一方で、`0xFE`で始まるバイト列を含むコントラクトのデプロイは成功すると予想されます。
これは、`0xFE`がそのような制限の対象ではないためです。

# 互換性

`0xEF`バイトで始まる新しいコードのデプロイが禁止されるという変更について説明しています。
この変更は「**破壊的変更（breaking change）**」であるとされており、それは新しい規則によって`0xEF`で始まるコードを持つ新しいコントラクトの作成が失敗に終わるためです。
しかし、バイトコード（スマートコントラクトのコード）は最初のバイトから実行されるため、最初のバイトが`0xEF`であるコードはいずれにしても実行不可能です。

### 破壊的変更
新しいコードが`0xEF`バイトで始まる場合、それをデプロイすることはできなくなります。
これは、特定のコードパターンの使用を禁止することにより、既存のデプロイプロセスや契約の作成方法に大きな変更をもたらすため、「**破壊的**」とされています。

### 実行不可能なコード
`0xEF`で始まるコードは、その最初のバイトから実行されるため実行不可能です。
これは、`0xEF`バイトが未定義の命令（つまり、EVMがどのように処理すべきかを知らない命令）であるためです。

### 既存の実行可能コントラクトへの影響なし
この変更は既にデプロイされている、実行可能なコントラクトには影響しません。
つまり、現在動作しているコントラクトはこの変更によって影響を受けることはありません。

### 新しいデータコントラクトのデプロイ拒否
しかし、この変更は`0xEF`バイトで始まる新しい「**データコントラクト**」のデプロイを拒否します。
データコントラクトとは、主にデータの保存や管理を目的としたスマートコントラクトのことを指します。
このようなコントラクトは、実行可能なコードを含まないことが多いため、最初のバイトが0xEFであっても実用的な可能性がありましたが、この変更によりそのような新しいコントラクトのデプロイはできなくなります。

この変更は新しいコントラクトのデプロイ方法に大きな影響を及ぼしますが、既存の実行可能なコントラクトには影響を与えないという点に注意が必要です。

# セキュリティ

この提案による変更がもたらすセキュリティやDoSのリスクを特に認識していないです。

# 引用

Alex Beregszaszi (@axic), Paweł Bylica (@chfast), Andrei Maiboroda (@gumb0), Alexey Akhunov (@AlexeyAkhunov), Christian Reitwiessner (@chriseth), Martin Swende (@holiman), "EIP-3541: Reject new contract code starting with the 0xEF byte," Ethereum Improvement Proposals, no. 3541, March 2021. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-3541.

# 最後に

今回は「EVM Object Format（EOF）に準拠するコントラクトをデプロイ時に検証するため、`0xEF`バイトで始まる新コードのデプロイを禁止する提案している**EIP3541**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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