はじめに

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

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

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

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

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

変更点

Solidityのバージョン0.8.27では以下の項目が変更されました。

  • requireでのカスタムエラーサポート
  • IRキャッシュの最適化
  • その他

requireでのカスタムエラーサポート

Solidityのバージョン0.8.26でrequireでカスタムエラーのサポートはされていました。

具体的にどのように使用するかなども以下にまとめています。

しかし、IRパイプライン(Yul経由でのコンパイル)でのみ機能の使用ができました。 Version 0.8.27からはYul経由でなくてもこの機能を使用できるようになりました。

IRキャッシュの最適化

IR(中間表現)パイプラインのパフォーマンスを改善します。

IR(中間表現)パイプラインとは?

コンパイラがコントラクトのソースコードを直接バイトコードに変換するのではなく、一度中間表現に変換してからバイトコードに変換します。 これにより、複雑なコントラクトを段階的に変換し、コンパイルの効率を高めたり最適化(ガスコストの削減や実行速度の向上)をしてくれます。

Solidityでコントラクトをコンパイルするとき、別のコントラクトのバイトコードに依存している場合、そのバイトコードを読み込む必要があります。 例えば、new演算子を使って新しいコントラクトをデプロイする時や、.runtimeCodeや.creationCodeを参照する時です。

new演算子

既存のコントラクトから別のコントラクトを作成する時に使われます。 この場合、コンパイラは、新しく作成されるコントラクトのバイトコード(実際にブロックチェーン上で実行されるコード)を、デプロイ元のコントラクトに依存関係として組み込む必要があります。 この組み込みがIRパイプラインの中で処理されます。

.runtimeCodeや.creationCodeを参照する場合

  • .runtimeCode
    • コントラクトがデプロイされた後に実行されるバイトコードを指します。
    • コントラクトのデプロイ後にそのコードが必要な場合、デプロイ元のコントラクトはそのコードを参照します。
  • .creationCode
    • コントラクトを作成する際に使われるバイトコードです。
    • コントラクトが最初にデプロイされるときに使用されます。

これまでのIRパイプラインでは、この依存するバイトコードを早い段階(Yulコード生成時)で組み込んでいました。 これにより、すべてのコードが一体化され、外部リンクの必要がなくなるというメリットがありましたが、依存するコントラクトが何度も参照されるたびに、そのコントラクトが再度最適化されてしまうという問題がありました。 同じコントラクトが何度も最適化プロセスを繰り返し、コンパイル時間が大幅に増えてしまいます。

この問題に対して、Version 0.8.27では「キャッシュ機能」を導入し、依存するコントラクトが最初に最適化された結果を再利用できるようにしています。 これにより、同じコントラクトが複数回最適化されるのを避け、パフォーマンスの向上につながります。

具体的には、Yulオブジェクトレベルでのキャッシュが導入され、Yulオブジェクトが最適化された時にその結果を次回以降のコンパイルで使いまわせるようになっています。

以下のように、このキャッシュ機能により、特定のプロジェクトでは大きなスピードアップが実現されました。

Project Effect
OpenZeppelin 影響なし(最適化に依存する部分が少ないため)
Uniswap v4 42%の速度向上
Eigenlayer 44%の速度向上

その他

テストでのnewコスト削減

newを使用して新しいコントラクトをデプロイすることはテストコードでもよくあります。 しかし、依存するコントラクトが何度も最適化されてしまい、コンパイルが遅くなることがありました。 Version 0.8.28ではキャッシュ機能を導入することで、依存するコントラクトの最適化結果を再利用してコンパイル速度を改善しています。

Transient Storageサポート

新しい一時的なストレージ変数です。 EthereumのアップグレードであるDencunアップデートで導入される予定の機能です。

Version 0.8.27では文法のサポートがされています。 ただし、機能自体はまだサポートされていないため、今後のバージョンアップで対応されるようです。

以下の記事でわかりやすくまとめられています。

--strict-assemblyと--yulオプションの違い

Solidityでは、Yulという中間言語を使ってコントラクトを最適化する時--yulオプションが使われていました。 今回のリリースで、--yulオプションで使われていた実験的な型付きYulダイアレクトが廃止され、今後は--strict-assemblyオプションが一般的なYulコンパイルに使用されます。 Yul自体のサポートは引き続き維持されます。

その他の変更

その他の細かい修正については以下の記事を参考にしてください。

最後に

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

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