本文へ移動

Ethereum Virtual Machine(EVM)

フォークを踏まえ、EVM のトランザクション、メッセージコールフレーム、バイトコード、スタック、メモリ、ストレージ、ガス、REVERT、DELEGATECALL、プリコンパイル、レシート、状態照合を解説します。

更新日

教育目的の情報であり、投資またはセキュリティに関する助言ではありません。EVM の挙動は、対象のチェーン、フォーク、状態、バイトコード、呼び出しコンテキスト、ガス体系、クライアント、プロトコル更新に依存します。

直接の答え

Ethereum Virtual Machine は、特定フォークの規則に従ってバイトコードを解釈する実行レイヤーの状態遷移マシンです。同一の有効な事前状態、トップレベルのトランザクションまたはメッセージ、ブロック環境、フォーク仕様が与えられれば、仕様に準拠する実行クライアントは同一の事後状態または失敗結果を算出しなければなりません。EVM はトランザクションの順序を決めず、コンセンサスのファイナリティを提供せず、フロントエンドを認証せず、EVM 互換チェーンすべてを Ethereum と同程度に安全にするものでもありません。

外部署名されたトランザクションは、トップレベルのプロトコルオブジェクトです。コントラクト間の活動は、入れ子になったメッセージコールとコールフレームで構成され、各々がトランザクション nonce、レシート、ハッシュを持つ独立トランザクションではありません。各フレームはコード、プログラムカウンタ、256 ビットスタック、メモリ、calldata、returndata、ガス、実行コンテキストを持ちます。永続ストレージはアカウントに属し、トランジェントストレージの寿命は対象フォークの規則に従って一つのトランザクション内に限られます。

仕組み

  1. 実行スナップショットを固定します。チェーンと chainId、ネットワーク、ブロック番号とハッシュ、正規または確定済みの状態、フォーク、実行クライアントと仕様改訂、事前状態または状態ルート、トランザクション型、署名済みの生バイト列、トランザクションハッシュ、レシートを記録します。決定性は、この正確なコンテキストを条件とします。
  2. トランザクションエンベロープを復号し、実行前の有効性と実行結果を分けます。署名と送信者、nonce、宛先またはコントラクト作成、value、calldata、ガス上限、手数料フィールド、アクセスリスト、型固有フィールドを検証します。ブロック収録前に拒否されたトランザクションは、収録後に実行されてリバートしたトランザクションではありません。
  3. トップレベルメッセージと完全なコールツリーを構築します。CALLSTATICCALLDELEGATECALL、コントラクト作成、プリコンパイルの各フレームについて、呼び出し元、コンテキストアドレス、コードアドレス、msg.sendermsg.value、value 移転、calldata、returndata、転送ガス、成功フラグを記録します。エクスプローラーの「内部トランザクション」はトレース表示であり、署名済みトランザクションではありません。
  4. 各フレームのプログラムカウンタ、スタック、メモリ、calldata、returndata、ログ、永続ストレージ、トランジェントストレージのジャーナルを追跡します。CALL は呼び出し先のアドレスとストレージコンテキストを使用します。DELEGATECALL は呼び出し元のアドレスとストレージコンテキストで対象コードを実行し、上流の送信者と value を維持します。STATICCALL では状態変更が禁止されます。
  5. 対象フォークのガス規則を適用します。固有ガス、オペコードの動的コスト、メモリ拡張、コールドアクセスとウォームアクセス、コールへのガス転送、stipend、プリコンパイル料金、refund とその上限を計算します。その後、使用ガスと実効ガス価格を用いて、トランザクション手数料を value とは分けて計算します。ガス見積もりは条件付きであり、保証ではありません。
  6. フレームの結果をスコープごとに確定します。祖先フレームが最終的にコミットすれば、RETURN はそのフレームをコミットします。REVERT はそのフレームと子孫を巻き戻してデータを返しますが、フレームの残りガスを必ずしも使い切りません。例外停止は別の挙動です。親は失敗した低水準コールを捕捉して処理を続けられるため、子が失敗してもトップレベルのレシートステータスは 1 になり得ます。収録されたトップレベル実行が失敗しても、送信者の nonce と実際に支払ったガスは消費されます。
  7. レシートステータス、使用ガス、ログ、作成アドレス、返却データを、事前・事後状態の残高、nonce、コード、永続・トランジェントストレージ、トークン台帳、トレース、ブロック状態ルートと照合します。必要に応じて独立クライアントで再実行し、プロキシ実装、ストレージレイアウト、プリコンパイル、コンパイラの EVM ターゲット、フォーク更新をコンセンサスのファイナリティとは別に監査します。

計算例

  • 収録済みトップレベルリバートと手数料台帳。 タイプ 2 トランザクションのガス上限が 80,000、使用ガスが 52,000、ベースフィーが 20 gwei、最大プライオリティフィーが 3 gwei、最大フィーが 40 gwei とします。実効ガス価格は min(40, 20 + 3) = 23 gwei、実際の手数料は 52,000 * 23 gwei = 0.001196 ETH です。内訳は、バーンされる 52,000 * 20 gwei = 0.001040 ETH とプライオリティフィー 52,000 * 3 gwei = 0.000156 ETH です。未使用の 28,000 gas は課金されません。トップレベル実行がリバートすると、ストレージ、value 移転、ログの効果は巻き戻りますが、送信者 nonce と実際の手数料は残ります。
  • 捕捉された子コールの失敗。 コントラクト A の初期値を A.x = 5 とします。A が B を呼び出し、B は B.y = 9 と書き込み、ログを発行して REVERT を実行します。B の書き込みとログは巻き戻ります。A は success = false を確認し、A.x = 7 と書き込んで正常に返ります。最終レシートステータスは 1A.x = 7 で、B は以前の値を保ちます。したがって、トップレベルの成功はすべての子コールの成功を証明しません。
  • DELEGATECALL のストレージコンテキスト。 プロキシの slot0 = 5、実装アカウントの slot0 = 99 とします。実装コードはスロット 0 を読み、7 を足して書き戻します。DELEGATECALL 経由で実行すると、プロキシは slot0 = 12 に変わり、実装アカウントは slot0 = 99 のままです。プロキシのアドレスとストレージコンテキストが使われ、上流の送信者と value は維持されます。互換性のないストレージレイアウトはプロキシ状態を破壊し得ます。
  • フォークに依存する SELFDESTRUCT。 EIP-6780 の規則下で、残高 2 ETH の既存コントラクトが受益者 B に対して SELFDESTRUCT を実行するとします。B は 2 ETH を受け取り、コントラクト残高はゼロになりますが、既存のアカウント、コード、ストレージは削除されません。削除の挙動が残るのは、同一トランザクション内で作成され自壊した場合だけです。これはフォークに依存する挙動であり、過去やすべての EVM チェーンに外挿できません。

リスク

  • 誤ったチェーン、ブロック、フォーク、クライアント、事前状態で再実行すること。
  • 非正規または再編成で置き換えられた状態を最終実行コンテキストとみなすこと。
  • 事前検証での拒否と収録後の実行リバートを混同すること。
  • pending 状態のシミュレーションが後の収録状態と一致すると仮定すること。
  • トップレベルのリバート、例外停止、ガス不足を見落とすこと。
  • 親に捕捉された子コールの失敗を見落とすこと。
  • 呼び出しコンテキスト、コードアドレス、呼び出し元、送信者、value を誤読すること。
  • DELEGATECALL のストレージレイアウト不一致でプロキシ状態を破壊すること。
  • リエントランシー、または安全でない外部への value と制御の移転を許すこと。
  • 未検証の returndata、成功フラグ、カスタムエラーを信頼すること。
  • ログやトレースを権威ある最終状態とみなすこと。
  • コールド・ウォームアクセス、メモリ、コール転送ガスを誤算すること。
  • refund、refund 上限、stipend、63/64 規則を誤用すること。
  • 誤ったプリコンパイルアドレス、入力、ガス規則、フォークの挙動を用いること。
  • 永続ストレージ、メモリ、トランジェントストレージの寿命を混同すること。
  • STATICCALL 内で状態変更が成功すると想定すること。
  • EIP-6780 より前の SELFDESTRUCT 削除前提を適用すること。
  • プロキシ実装、管理者、コンパイラターゲットの変更を見落とすこと。
  • 規則が異なる、または未更新の実行クライアントを稼働させること。
  • EVM 互換性からコンセンサス、ブリッジ、トークン、ガバナンス、ファイナリティの安全性を推論すること。

よくある誤解

  • Solidity ソースコードがオンチェーンで直接実行される対象である。
  • 収録済みトランザクションがリバートすれば手数料はかからず、nonce も変わらない。
  • レシートステータス 1 は、すべての内部コールが意図どおり成功した証拠である。
  • イベントやトレースが、権威ある資産・ストレージ状態である。
  • EVM 互換性は、オペコード、ガス、プリコンパイル、コンセンサス、安全性が同一であることを保証する。

関連トピック

出典

ナビゲーション

Wiki を検索...