はじめに

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

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください!

今回はSolidityのバージョン0.8.30での変更点をまとめていきます。

以下の公式のリリース記事をもとにまとめていきます。

変更点

Ethereumの次期ハードフォーク「Pectra」では、Solidityの挙動やコントラクト設計に直接的な影響を与える複数のEIPが導入されます。

  • EIP7623: calldataのコスト増加
  • EIP7702: EOAアカウントにコードを設定可能に
  • EIP2537: BLS12381カーブのプリコンパイル対応

EIP7623: calldataのコスト増加

Pectraでは、EIP7623によりトランザクションの calldata(外部から送られる読み取り専用データ)に対するガスコストが増加します。 これは、EIP7691によってブロックの最大サイズが増加することへの対策として、過剰なデータ投稿による帯域負担を抑制する目的があります。

この変更は、Solidityコンパイラ内部の最適化処理、特に ConstantOptimizer のような定数圧縮のアルゴリズムに影響する可能性があります。 例えば、2256−12^{256} - 1という値をエンコードする際、以下の2通りの表現があります。

  • PUSH32 0xffff...ffff(ガスコスト3、サイズ33バイト)
  • PUSH0 NOT(ガスコスト5、サイズ2バイト)

このような選択では、calldata サイズもコストの一部として評価されるため、コスト増加が最適化判断に影響する余地があります。

しかし、今回のコンパイラアップデートでは明示的な調整は行われていません。 理由は以下の通りです。

  • コスト増加が非局所的(実行されるトランザクション全体の内容・状態・分岐経路に依存する)であり、個々のオペコードレベルで適切に反映することが難しい。
  • ユーザーが--optimizer-runsフラグを調整することで、デプロイ時と実行時のコストバランスを柔軟にコントロールできる。

つまり、calldata コストの変化は最適化パラメータの設定によって対処可能であり、特別な対応は不要という判断です。

Solidityの最適化ロジック(たとえば定数の扱いや PUSH 命令の選び方など)は、--optimizer-runs に応じて以下のように振る舞います。

  • runs が 少ない(例: 1〜10)
    • 「1回の呼び出しでコスト安い方がいい」ため、コードを短くして低デプロイgasを選択
  • runs が 多い(例: 100000)
    • 「何度も呼ばれるので実行gasが少ない方がいい」ため 多少サイズが大きくても処理が軽い選択

つまり、calldata コストが上がった = デプロイコストが増えたとしても、それを考慮して --optimizer-runs を小さくして、よりデプロイ効率を重視するように切り替えることができます。

EIP7702: EOAアカウントにコードを設定可能に

EIP7702では、外部所有アカウント(EOA)にもコードを設定できる新しいトランザクション形式が導入されます。 これにより、EOAが任意のコントラクトに権限を委任(delegate)することで、EOAがコントラクトアカウントのように振る舞うことが可能になります。

EIP7702については以下の記事を参考にしてください。

これは、Ethereumが目指すAccount Abstraction(アカウント抽象化)への重要な一歩であり、より柔軟な署名検証やウォレット機能をEOAにもたらします。

Solidityコンパイラ自体は今回特にこのEIPへの対応は行っていませんが、前バージョン(v0.8.29)では複数のdelegateがEOAのストレージを安全に共有できるように、ストレージレイアウト制御が追加されていました。

EIP2537: BLS12381カーブのプリコンパイル対応

EIP2537は、BLS署名の検証をEthereum上で可能にするプリコンパイル(事前コンパイル済みのネイティブコード)を導入します。 BLS署名は、以下の理由から期待されていました。

  • 署名の集約が可能(複数署名を1つにまとめられる)
  • Ethereumのコンセンサス層ではすでに使用されている

今回のプリコンパイルは、Solidityに新しい文法や構文を導入することなく、既存の低レベル関数呼び出し(call)を通じて使用可能です。

Solidityチームとしては、BLS操作のような高度な機能は言語に直接組み込むのではなく、外部ライブラリに任せる方が適切だと判断しています。 そのため、現時点ではSolidityにBLS操作用のグローバル関数は用意されていません。

ただし、将来的に標準ライブラリに含める可能性は否定されておらず、ユースケースのフィードバックは歓迎されています。

その他の変更

EthereumのPectraアップグレードに対応したSolidityコンパイラでは、いくつかの新機能とバグ修正が加えられました。

コンパイラ機能の追加

EVMバージョンのデフォルト設定を「prague」に変更

コンパイル時に特定のEVMバージョン(例:london, parisなど)を指定しない場合、自動的に「prague」バージョンでコンパイルされるようになりました。

これにより、Pectraで導入される新しいEIP(例:EIP7702やEIP7623)を使用する場合でも、明示的に --evm-version を指定しなくても問題なく対応できます。

NatSpecコメント:enumの値に対応

NatSpec(ドキュメンテーションコメント)によるドキュメント生成が改善され、列挙型(enum)の各値に付けたコメントがAST(抽象構文木)に取り込まれるようになりました。

これにより、ドキュメンテーションツールや開発支援ツールが、enumの各値の意味をより正確に取得・表示できるようになります。

バグ修正

ループ条件の誤った定数評価を修正

SMTCheckerにおいて、ループ条件が常に真または偽だと誤判定される問題が修正されました。 これにより、不正確な警告や内部コンパイラエラーの発生が防がれます。

SMTとは?

SMTとは、Satisfiability Modulo Theories(理論付き充足可能性)の略です。

これは「特定の条件(制約)が数学的に満たされるかどうか」を自動的にチェックするための検証手法です。

例えば、以下のように数学的に成り立つかどうか(正しさ)を証明しようとするものです。

  • 「この変数は常に0以上になるか?」
  • 「このif文の中に入る可能性はあるか?」
  • 「この関数でオーバーフローは起きないか?」

SMTCheckerとは?

SMTCheckerは、Solidityコンパイラに組み込まれている機能で、SMTを使ってスマートコントラクトの安全性や論理的な正しさを自動検証するツールです。

  • 整数のオーバーフローやアンダーフローが起きないか検出
  • 条件分岐(require, assertなど)が常に満たされるかを検証
  • 到達不能コード(実行されることが絶対にないコード)を検出

--model-checker-contracts 使用時の誤解析を修正

特定のコントラクトのみを対象にSMTによる検証を行う際に、他のコントラクトのステートが考慮されて誤った解析結果が出る問題がありましたが、これが修正されました。

固定長バイト型に基づくユーザー定義型の初期化での内部エラーを修正

ユーザー定義型(typedef)をbytes4などの固定長バイト型から作成し、それを文字列リテラルで初期化する場合に発生していた内部コンパイラエラーが修正されました。

最後に

今回はSolidityのバージョン0.8.30の変更点をまとめました。

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください!