コンパイラチームが報告した内容
Solidityチームは9月10日、主にバグ修正を目的とするバージョン0.8.37を公開しました。発表では重要な修正が3件示され、2件は重要度が「低・中」、1件は「非常に低」と評価されています。前者2件は特定のコンパイラパイプラインでメモリを黙って上書きする可能性があり、後者はコントラクト状態を変えないものの、カスタムエラーのデータを誤った順序で生成し得ます。
従来のevmasmパイプラインでは、メモリ上のbytes配列から1要素をdeleteすると、その位置から32バイトがゼロ化され、後続の最大31バイトを上書きする可能性がありました。bytesへ変換したstringにも同じ挙動があり、0.8.36以前の全バージョンが影響を受けます。IRパイプラインとb[i] = 0による代入は影響を受けません。別件では、0.7.2から0.8.36を--via-irでコンパイルした場合、相互再帰する関数が同時に有効な特定の状況でスピルスロットが重複し、生存中の変数を別の変数が上書きし得ます。
バージョンの棚卸しだけでは不十分
影響バージョンの範囲は最初の絞り込みにすぎません。影響の有無は、コンパイラパイプラインとソースコード上のパターンに依存します。一方はevmasmとメモリ上のbyte要素へのdelete、もう一方は--via-irと、スタックからメモリへの退避を発生させる相互再帰のコールグラフが条件です。そのため、各デプロイ済みバイトコードを、solcバージョン、最適化設定、EVMターゲット、パイプライン、ソースコミット、依存関係ロックファイル、ビルドシステムの版へ結び付ける必要があります。
影響判定の前に、その証跡を検証済みソースとコンパイラメタデータに照合します。プロキシ群ではプロキシと実装のバイトコードを別々に記録し、ライブラリや生成コードも検索対象に含めます。「Solidity 0.8系でビルド」では粗すぎます。「このコミットと設定から0.8.36、via IR有効で再現可能にビルド」という情報なら、根拠のある判断ができます。
ツールチェーンを修正し、挙動を証明する
新しいビルドでは0.8.37以降のレビュー済みリリースを固定し、コンパイラのバイナリまたはコンテナをダイジェストで検証します。pragmaの範囲だけを固定しても、開発環境とCIで異なるバイトコードが生成され得ます。既知の成果物を旧版と新版のコンパイラで再構築し、バイトコードとストレージレイアウトの差分を確認し、両方のビルドマニフェストを監査証跡として保存します。
回帰テストでは、コンパイル成功だけでなく発生条件を直接検証します。メモリ上のbytesでは、削除対象の後ろに番兵データを配置し、境界位置を変えながら隣接バイトがすべて保持されることを確認します。相互再帰では、退避が必要な数の生存ローカル変数を作り、再帰深度と呼び出し方向を変え、影響版と修正版の結果を比較します。どちらの不具合も有効なバイトコードと静かな誤値を生み得るため、ファジングと差分実行が特に有効です。
コンパイラ修正を危険な移行に変えない
コンパイラの新リリースは、デプロイ済みコントラクトすべての移行を自動的に意味しません。イミュータブルなコントラクトでは監視や後継経路が必要になり、アップグレード可能なシステムでもガバナンス承認、シミュレーション、タイムロック、ストレージレイアウト確認、ロールバックまたは一時停止手順が必要です。影響のないコントラクトを再デプロイすると、アドレス、allowance、外部連携、カストディポリシーの変更によって、修正前より大きなリスクを生む可能性があります。
ソースパターンが本番入力から到達可能で、上書きされる値が認可、会計、資産移動、可用性へ影響するコントラクトを優先します。各成果物を「影響あり」「影響なし」「未確定」とした理由を記録します。更新が必要なら、本番状態のフォーク上で手順をリハーサルし、実行後は不変条件、特権イベント、残高、エラー率を監視します。
Ineezaの見解
Solidity 0.8.37は、コンパイラの来歴が単なるビルド衛生ではなく、スマートコントラクトのセキュリティそのものであることを示します。運用上の目的は一律の更新ではありません。デプロイ済みバイトコードから、ビルド設定、影響するソースパターン、事業影響、テスト証跡、移行判断までを追跡可能にすることです。出荷物を再現できるチームはコンパイラ不具合を迅速に切り分けられます。できないチームは、本番リスクが不確定なまま、その証跡の復元から始めなければなりません。