イーサリアムスマートコントラクトのガス最適化のためのトップ10のベストプラクティス

この記事では、イーサリアムメインネット上のガス料金の問題と最適化方法について探求します。EVMのガスメカニズム、ガスコストを最適化するためのコアコンセプト、スマートコントラクトの開発のベストプラクティスに焦点を当てています。これには、ストレージ使用量の削減、変数のパッキング、データ型の最適化、固定サイズの変数の使用などが含まれます。

これらの実践に従うことで、開発者はスマートコントラクトでのガス消費を減らし、取引コストを下げ、より効率的でユーザーフレンドリーなアプリケーションを作成することができます。

イーサリアムメインネット上のガス料金は常に重大な問題であり、特にネットワークの混雑期には特にそうです。ピーク時には、ユーザーは非常に高いトランザクション料金を支払う必要があります。したがって、スマートコントラクトの開発段階でのガスコストの最適化は重要です。ガスの最適化により、トランザクションコストを効果的に削減するだけでなく、トランザクションの効率も向上し、ユーザーに経済的かつ効率的なブロックチェーン体験を提供できます。

この記事では、Ethereum Virtual Machine(EVM)のガス手数料メカニズム、ガス手数料最適化に関連する基本的なコンセプト、およびスマートコントラクトの開発時にガス手数料を最適化するためのベストプラクティスについて説明します。このコンテンツが開発者をインスパイアし、支援するとともに、EVMのガス手数料システムがどのように機能するかを一般のユーザーがより理解するのに役立つことを期待しています。これにより、ブロックチェーンエコシステム内の課題に対処することができます。

EVMガス料金メカニズムの概要

EVM互換ネットワークでは、「ガス」とは、特定の操作を実行するために必要な計算能力を測定するために使用される単位を指します。

以下の図はEVMの構造を示しています。図では、ガス消費は操作実行、外部メッセージ呼び出し、メモリとストレージの読み書きの3つの部分に分かれています。

ソース:イーサリアム公式ウェブサイト[1]

EIP-1559(ロンドンハードフォーク)の有効化以降、ガス手数料は以下の式を使用して計算されます:

ガス手数料=使用されたガスの単位数*(基本料金+優先料金)

ベース料金は燃やされ、優先料金はブロックチェーンにトランザクションを含めるためのバリデーターを促すためのインセンティブとなります。トランザクションを送信する際に優先料金を高く設定すると、次のブロックにトランザクションが含まれる可能性が高くなります。これは、ユーザーがバリデーターに支払う「チップ」に似ています。

1. EVM におけるガス最適化の理解

Solidityでスマートコントラクトをコンパイルする際、契約は「オペレーションコード」またはオペコードのシリーズに変換されます。

各オペコード(契約の作成、メッセージの呼び出し、アカウントストレージへのアクセス、仮想マシン上の操作の実行など)には、関連するガス消費コストがあります。これは、イーサリアムのイエローペーパー[2]に記載されています。

複数のEIPの修正後、一部のオペコードのガスコストが調整され、これはイエローペーパーの値と異なる場合があります。オペコードの最新コストの詳細については、このソース[3]を参照してください。

2. ガス最適化の基本概念

Gas最適化の核心コンセプトは、EVMブロックチェーン上でコスト効率の良い操作を優先し、高いGasコストを発生させる操作を避けることです。

EVMでは、次の操作は比較的低コストです:

  • [ ] メモリ変数の読み書き
  • [ ] 読み取り専用の定数および不変の変数
  • [ ] ローカル変数の読み書き
  • [ ] calldata配列や構造体などのcalldata変数の読み取り
  • [ ] 内部関数呼び出し

高コストな運用には次のものが含まれます:

  • [ ] コントラクトストレージに格納された状態変数の読み書き
  • [ ] 外部関数呼び出し
  • [ ] ループ操作

EVMガス料金の最適化のベストプラクティス

上記の基本的な概念に基づいて、開発者コミュニティのためにガス手数料の最適化のベストプラクティスのリストを作成しました。これらのプラクティスに従うことで、開発者はスマートコントラクトのガス消費を削減し、トランザクションコストを下げ、より効率的でユーザーフレンドリーなアプリケーションを作成することができます。

1. ストレージ使用量を最小限にする

Solidityでは、Storageは限られたリソースであり、そのGas消費量はMemoryよりもかなり高いです。スマートコントラクトがStorageから読み取りまたは書き込みを行うたびに、高いGasコストが発生します。

Ethereumイエローペーパーの定義によると、ストレージ操作のコストはメモリ操作よりも100倍以上高いです。たとえば、sloadやsstoreなどのオペコードは、最良の場合でも少なくとも100ガス単位かかりますが、mloadやmstoreなどのメモリ操作はたった3ガス単位しか消費しません。

ストレージ使用量を制限する方法は、次のとおりです:

  • [ ]メモリに非永続的なデータを保存
  • [ ]ストレージの変更回数を減らす:中間結果をメモリに保存し、すべての計算が完了した後に最終結果をストレージ変数に割り当てることで、ストレージの変更回数を減らします。

2. 変数のパッキング

スマートコントラクトで使用されるストレージスロットの数と、開発者がデータを表現する方法は、ガス消費に大きな影響を与える可能性があります。

ソリディティコンパイラは、コンパイルプロセス中に連続するストレージ変数をパックし、変数ストレージの基本単位として32バイトのストレージスロットを使用します。変数のパッキングとは、複数の変数が単一のストレージスロットに収まるように変数を配置することを指す。

左側は3つのストレージスロットを消費する効率の低い実装です。右側はより効率的な実装です。

この調整を行うことで、開発者は20,000ガスユニットを節約することができます(未使用のストレージスロットの保存には20,000ガスがかかります)、しかし現在は2つのストレージスロットのみが必要です。

各ストレージスロットがガスを消費するため、変数のパッキングは、必要なストレージスロットの数を減らすことにより、ガスの使用を最適化します。

3. データ型の最適化

変数は異なるデータ型を使用して表現することができますが、操作のコストは型によって異なります。適切なデータ型を選択することで、Gasの使用を最適化するのに役立ちます。

例えば、Solidityでは、整数は異なるサイズに細分化できます:uint8、uint16、uint32など。EVMは256ビット単位で動作するため、uint8を使用すると、EVMはまずuint256に変換しなければならず、この変換には追加のガスコストがかかります。

図のコードを使用して、uint8とuint256のGasコストを比較することができます。 UseUint()関数は120,382ガスユニットを消費し、一方、UseUInt8()関数は166,111ガスユニットを消費します。

uint256を単独で使用すると、uint8よりも安価です。ただし、以前に提案された変数のパッキング最適化を適用すると、違いが生じます。開発者が4つのuint8変数を1つのストレージスロットにパックすることができる場合、それらを反復処理する総コストは4つのuint256変数を使用するよりも低くなります。この場合、スマートコントラクトはストレージスロットを1回読み取り、4つのuint8変数を1回の操作でメモリ/ストレージにロードすることができます。

4. 動的変数の代わりに固定サイズの変数を使用します

データが32バイトに制限できる場合は、bytesまたはstringsではなく、bytes32データ型を使用することをお勧めします。一般的に、固定サイズの変数は動的にサイズ変更する必要のある変数よりもガスを消費します。バイト長が制限できる場合は、bytes1からbytes32までの最小の長さを選択するようにしてください。

5. マッピング対配列

Solidityでは、データリストは2つのデータ型を使用して表すことができます:配列とマッピング。それぞれが異なる構文と構造を持っています。

一般的に、マッピングはほとんどの場合で効率的で費用対効果が高いですが、配列は反復可能でデータ型のパッキングをサポートしています。そのため、データリストを管理する場合は、反復が必要ない場合やデータ型のパッキングによってガス消費量を最適化できる場合を除き、マッピングの使用を優先することをお勧めします。

6. メモリの代わりにcalldataを使用してください

関数パラメータで宣言された変数は、calldataまたはmemoryに格納できます。主な違いは、memoryは関数によって変更可能であるのに対し、calldataは不変です。

この原則を心に留めておく: 関数パラメータが読み取り専用の場合は、メモリの代わりにcalldataを使用することをお勧めします。これにより、関数calldataからメモリへの不要なコピー操作が回避されます。

例1:メモリの使用

memoryキーワードを使用する場合、配列の値はABIデコード中にエンコードされたcalldataからmemoryにコピーされます。このコードブロックの実行コストは3,694 Gas単位です。

例2:calldataの使用

calldata から値を直接読み取る場合、中間メモリ操作はスキップされます。この最適化により、実行コストはわずか2,413ガスユニットに削減され、ガス効率が35%向上します。

7. 可能な限りConstant/Immutableキーワードを使用してください

定数/不変の変数は契約のストレージに格納されていません。これらの変数はコンパイル時に計算され、契約のバイトコードに格納されます。したがって、アクセスコストはストレージ変数と比較してはるかに低くなります。可能な限りConstantまたはImmutableキーワードを使用することをお勧めします。

8. オーバーフロー/アンダーフローが心配されない場合は、無確認を使用します

開発者が算術演算がオーバーフローまたはアンダーフローにならないことを確信できる場合、Solidity v0.8.0で導入されたuncheckedキーワードを使用して、不要なオーバーフローまたはアンダーフローチェックを回避し、ガスコストを節約することができます。

以下の図において、条件付き制約のあるi

また、コンパイラのバージョン0.8.0以上では、SafeMathライブラリの使用が不要になりました。なぜなら、コンパイラ自体にオーバーフローとアンダーフローの保護が組み込まれているからです。

9. 修飾子を最適化する

修飾子のコードは、修飾する関数に埋め込まれます。修飾子が使用されるたびに、そのコードが複製され、バイトコードのサイズが増え、ガスの消費量が増加します。修飾子のガスコストを最適化する方法の一つは次のとおりです:

最適化前:

最適化後:

この例では、修正を行い、修飾子で再利用できる内部関数_checkOwner()にロジックを再構築することにより、バイトコードサイズが削減され、ガスコストが低減されます。

10. ショートサーキット最適化

||(または)および&&(および)演算子の場合、論理演算はショートサーキット評価で行われます。これは、最初の条件が論理式の結果を決定するのに十分な場合、2番目の条件は評価されません。

ガス消費を最適化するためには、計算コストの低い条件を最初に配置し、可能性のある高価な計算をスキップできるようにする必要があります。

一般的な推奨事項

1. 未使用のコードを削除する

契約に未使用の関数や変数がある場合は、それらを削除することをお勧めします。これは契約のデプロイメントコストを削減し、契約のサイズを小さく保つための最も直接的な方法です。

以下はいくつかの実用的な提案です:

計算には最も効率的なアルゴリズムを使用してください。契約が特定の計算結果を直接使用する場合、不要な計算を取り除く必要があります。基本的に、未使用の計算は削除されるべきです。イーサリアムでは、開発者はストレージスペースを解放することでガスの報酬を受け取ることができます。変数がもはや必要ない場合は、削除キーワードを使用するか、そのデフォルト値に設定する必要があります。

ループの最適化:高コストのループ操作を避け、ループを統合し、繰り返し計算をループの本体から移動させてください。

2. 事前コンパイルされた契約の使用

プリコンパイル済みのコントラクトは、暗号化やハッシュ操作などの複雑なライブラリ機能を提供します。コードはEVM上で実行されるのではなく、クライアントノードでローカルに実行されるため、より少ないガスが必要です。プリコンパイル済みのコントラクトを使用すると、スマートコントラクトの実行に必要な計算作業量を減らすことでガスを節約することができます。

事前にコンパイルされた契約の例には、楕円曲線デジタル署名アルゴリズム(ECDSA)やSHA2-256ハッシュアルゴリズムが含まれます。これらの事前にコンパイルされた契約をスマートコントラクトで使用することで、開発者はガスコストを削減し、アプリケーションの効率を向上させることができます。

Ethereumネットワークでサポートされている事前コンパイル済み契約の完全なリストについては、このリンク[4]を参照してください。

3. インラインアセンブリの使用

インラインアセンブリは、高価なSolidityオペコードを使用せずにEVMによって直接実行される、低レベルで効率的なコードを開発者が記述することを可能にします。インラインアセンブリは、メモリとストレージの使用に対してより正確な制御も可能であり、さらにガスコストを削減します。さらに、インラインアセンブリはSolidity単体では実装が困難な複雑な操作を実行することもでき、ガス消費の最適化に対してより柔軟性を提供します。

ガスを節約するためにインラインアセンブリを使用する例を示します:

上記の例で見られるように、インラインアセンブリを使用する2番目のケースは、標準のケースと比較してガス効率が高いです。

ただし、インラインアセンブリを使用することはリスクをもたらす可能性があり、エラーが発生する可能性もあります。そのため、慎重に使用し、経験豊富な開発者にのみ推奨されます。

4. レイヤー2ソリューションの使用

Layer 2ソリューションは、Ethereumメインネット上で保存および計算する必要があるデータ量を削減することができます。

ロールアップ、サイドチェーン、およびステートチャネルなどのレイヤー2ソリューションは、主要なイーサリアムチェーンからトランザクション処理をオフロードし、より高速かつ安価なトランザクションを可能にします。

これらのソリューションは、大量のトランザクションをまとめることによって、オンチェーンのトランザクション数を減らし、それによってガス料金を低く抑えることができます。Layer 2のソリューションを使用することで、Ethereumのスケーラビリティが向上し、過負荷による混雑を引き起こすことなく、より多くのユーザーとアプリケーションがネットワークに参加できるようになります。

5. 最適化ツールとライブラリの使用

いくつかの最適化ツールが利用可能です。solcオプティマイザー、Truffleのビルドオプティマイザー、およびRemixのSolidityコンパイラなどがあります。

これらのツールは、バイトコードのサイズを最小化し、未使用のコードを削除し、スマートコントラクトの実行に必要な操作の数を減らすのに役立ちます。 「solmate」などの他のGas最適化ライブラリと組み合わせることで、開発者は効果的にGasコストを削減し、スマートコントラクトの効率を改善することができます。

結論

ガス消費の最適化は、開発者にとって重要なステップです。なぜなら、これによりトランザクションコストを最小化し、EVM互換ネットワーク上のスマートコントラクトの効率を向上させることができるからです。費用削減の操作を優先し、ストレージ使用量を減らし、インラインアセンブリを活用し、本記事で説明されている他のベストプラクティスに従うことで、開発者は契約のガス消費を効果的に低下させることができます。

ただし、最適化プロセス中には、開発者が注意を払い、セキュリティの脆弱性を導入しないよう注意する必要があります。コードの最適化とガス消費の削減の過程で、スマートコントラクトの固有のセキュリティが決して危険にさらされてはなりません。

[1]https://ethereum.org/en/developers/docs/gas/
[2] https://ethereum.github.io/yellowpaper/paper.pdf
[3]https://www.evm.codes/
[4] https://www.evm.codes/precompiled

免責事項:

  1. この記事は[から転載されましたPANewslab]. The copyright belongs to the original author [CertiK].転載に異議がある場合は、ゲートラーンチームは、関連手続きに従ってできるだけ早く対処します。
  2. 免責事項:この記事で表現されている見解や意見は、著者個人の見解を表しており、投資勧誘とはなりません。
  3. その他の言語版は、ゲートの学習チームによって翻訳されています。特に明記されていない限り、翻訳された記事は複製、配布、盗作することはできません。

イーサリアムスマートコントラクトのガス最適化のためのトップ10のベストプラクティス

中級1/3/2025, 11:25:57 AM
この記事では、イーサリアムメインネット上のガス料金の問題と最適化方法について探求します。EVMのガスメカニズム、ガスコストを最適化するためのコアコンセプト、スマートコントラクトの開発のベストプラクティスに焦点を当てています。これには、ストレージ使用量の削減、変数のパッキング、データ型の最適化、固定サイズの変数の使用などが含まれます。

これらの実践に従うことで、開発者はスマートコントラクトでのガス消費を減らし、取引コストを下げ、より効率的でユーザーフレンドリーなアプリケーションを作成することができます。

イーサリアムメインネット上のガス料金は常に重大な問題であり、特にネットワークの混雑期には特にそうです。ピーク時には、ユーザーは非常に高いトランザクション料金を支払う必要があります。したがって、スマートコントラクトの開発段階でのガスコストの最適化は重要です。ガスの最適化により、トランザクションコストを効果的に削減するだけでなく、トランザクションの効率も向上し、ユーザーに経済的かつ効率的なブロックチェーン体験を提供できます。

この記事では、Ethereum Virtual Machine(EVM)のガス手数料メカニズム、ガス手数料最適化に関連する基本的なコンセプト、およびスマートコントラクトの開発時にガス手数料を最適化するためのベストプラクティスについて説明します。このコンテンツが開発者をインスパイアし、支援するとともに、EVMのガス手数料システムがどのように機能するかを一般のユーザーがより理解するのに役立つことを期待しています。これにより、ブロックチェーンエコシステム内の課題に対処することができます。

EVMガス料金メカニズムの概要

EVM互換ネットワークでは、「ガス」とは、特定の操作を実行するために必要な計算能力を測定するために使用される単位を指します。

以下の図はEVMの構造を示しています。図では、ガス消費は操作実行、外部メッセージ呼び出し、メモリとストレージの読み書きの3つの部分に分かれています。

ソース:イーサリアム公式ウェブサイト[1]

EIP-1559(ロンドンハードフォーク)の有効化以降、ガス手数料は以下の式を使用して計算されます:

ガス手数料=使用されたガスの単位数*(基本料金+優先料金)

ベース料金は燃やされ、優先料金はブロックチェーンにトランザクションを含めるためのバリデーターを促すためのインセンティブとなります。トランザクションを送信する際に優先料金を高く設定すると、次のブロックにトランザクションが含まれる可能性が高くなります。これは、ユーザーがバリデーターに支払う「チップ」に似ています。

1. EVM におけるガス最適化の理解

Solidityでスマートコントラクトをコンパイルする際、契約は「オペレーションコード」またはオペコードのシリーズに変換されます。

各オペコード(契約の作成、メッセージの呼び出し、アカウントストレージへのアクセス、仮想マシン上の操作の実行など)には、関連するガス消費コストがあります。これは、イーサリアムのイエローペーパー[2]に記載されています。

複数のEIPの修正後、一部のオペコードのガスコストが調整され、これはイエローペーパーの値と異なる場合があります。オペコードの最新コストの詳細については、このソース[3]を参照してください。

2. ガス最適化の基本概念

Gas最適化の核心コンセプトは、EVMブロックチェーン上でコスト効率の良い操作を優先し、高いGasコストを発生させる操作を避けることです。

EVMでは、次の操作は比較的低コストです:

  • [ ] メモリ変数の読み書き
  • [ ] 読み取り専用の定数および不変の変数
  • [ ] ローカル変数の読み書き
  • [ ] calldata配列や構造体などのcalldata変数の読み取り
  • [ ] 内部関数呼び出し

高コストな運用には次のものが含まれます:

  • [ ] コントラクトストレージに格納された状態変数の読み書き
  • [ ] 外部関数呼び出し
  • [ ] ループ操作

EVMガス料金の最適化のベストプラクティス

上記の基本的な概念に基づいて、開発者コミュニティのためにガス手数料の最適化のベストプラクティスのリストを作成しました。これらのプラクティスに従うことで、開発者はスマートコントラクトのガス消費を削減し、トランザクションコストを下げ、より効率的でユーザーフレンドリーなアプリケーションを作成することができます。

1. ストレージ使用量を最小限にする

Solidityでは、Storageは限られたリソースであり、そのGas消費量はMemoryよりもかなり高いです。スマートコントラクトがStorageから読み取りまたは書き込みを行うたびに、高いGasコストが発生します。

Ethereumイエローペーパーの定義によると、ストレージ操作のコストはメモリ操作よりも100倍以上高いです。たとえば、sloadやsstoreなどのオペコードは、最良の場合でも少なくとも100ガス単位かかりますが、mloadやmstoreなどのメモリ操作はたった3ガス単位しか消費しません。

ストレージ使用量を制限する方法は、次のとおりです:

  • [ ]メモリに非永続的なデータを保存
  • [ ]ストレージの変更回数を減らす:中間結果をメモリに保存し、すべての計算が完了した後に最終結果をストレージ変数に割り当てることで、ストレージの変更回数を減らします。

2. 変数のパッキング

スマートコントラクトで使用されるストレージスロットの数と、開発者がデータを表現する方法は、ガス消費に大きな影響を与える可能性があります。

ソリディティコンパイラは、コンパイルプロセス中に連続するストレージ変数をパックし、変数ストレージの基本単位として32バイトのストレージスロットを使用します。変数のパッキングとは、複数の変数が単一のストレージスロットに収まるように変数を配置することを指す。

左側は3つのストレージスロットを消費する効率の低い実装です。右側はより効率的な実装です。

この調整を行うことで、開発者は20,000ガスユニットを節約することができます(未使用のストレージスロットの保存には20,000ガスがかかります)、しかし現在は2つのストレージスロットのみが必要です。

各ストレージスロットがガスを消費するため、変数のパッキングは、必要なストレージスロットの数を減らすことにより、ガスの使用を最適化します。

3. データ型の最適化

変数は異なるデータ型を使用して表現することができますが、操作のコストは型によって異なります。適切なデータ型を選択することで、Gasの使用を最適化するのに役立ちます。

例えば、Solidityでは、整数は異なるサイズに細分化できます:uint8、uint16、uint32など。EVMは256ビット単位で動作するため、uint8を使用すると、EVMはまずuint256に変換しなければならず、この変換には追加のガスコストがかかります。

図のコードを使用して、uint8とuint256のGasコストを比較することができます。 UseUint()関数は120,382ガスユニットを消費し、一方、UseUInt8()関数は166,111ガスユニットを消費します。

uint256を単独で使用すると、uint8よりも安価です。ただし、以前に提案された変数のパッキング最適化を適用すると、違いが生じます。開発者が4つのuint8変数を1つのストレージスロットにパックすることができる場合、それらを反復処理する総コストは4つのuint256変数を使用するよりも低くなります。この場合、スマートコントラクトはストレージスロットを1回読み取り、4つのuint8変数を1回の操作でメモリ/ストレージにロードすることができます。

4. 動的変数の代わりに固定サイズの変数を使用します

データが32バイトに制限できる場合は、bytesまたはstringsではなく、bytes32データ型を使用することをお勧めします。一般的に、固定サイズの変数は動的にサイズ変更する必要のある変数よりもガスを消費します。バイト長が制限できる場合は、bytes1からbytes32までの最小の長さを選択するようにしてください。

5. マッピング対配列

Solidityでは、データリストは2つのデータ型を使用して表すことができます:配列とマッピング。それぞれが異なる構文と構造を持っています。

一般的に、マッピングはほとんどの場合で効率的で費用対効果が高いですが、配列は反復可能でデータ型のパッキングをサポートしています。そのため、データリストを管理する場合は、反復が必要ない場合やデータ型のパッキングによってガス消費量を最適化できる場合を除き、マッピングの使用を優先することをお勧めします。

6. メモリの代わりにcalldataを使用してください

関数パラメータで宣言された変数は、calldataまたはmemoryに格納できます。主な違いは、memoryは関数によって変更可能であるのに対し、calldataは不変です。

この原則を心に留めておく: 関数パラメータが読み取り専用の場合は、メモリの代わりにcalldataを使用することをお勧めします。これにより、関数calldataからメモリへの不要なコピー操作が回避されます。

例1:メモリの使用

memoryキーワードを使用する場合、配列の値はABIデコード中にエンコードされたcalldataからmemoryにコピーされます。このコードブロックの実行コストは3,694 Gas単位です。

例2:calldataの使用

calldata から値を直接読み取る場合、中間メモリ操作はスキップされます。この最適化により、実行コストはわずか2,413ガスユニットに削減され、ガス効率が35%向上します。

7. 可能な限りConstant/Immutableキーワードを使用してください

定数/不変の変数は契約のストレージに格納されていません。これらの変数はコンパイル時に計算され、契約のバイトコードに格納されます。したがって、アクセスコストはストレージ変数と比較してはるかに低くなります。可能な限りConstantまたはImmutableキーワードを使用することをお勧めします。

8. オーバーフロー/アンダーフローが心配されない場合は、無確認を使用します

開発者が算術演算がオーバーフローまたはアンダーフローにならないことを確信できる場合、Solidity v0.8.0で導入されたuncheckedキーワードを使用して、不要なオーバーフローまたはアンダーフローチェックを回避し、ガスコストを節約することができます。

以下の図において、条件付き制約のあるi

また、コンパイラのバージョン0.8.0以上では、SafeMathライブラリの使用が不要になりました。なぜなら、コンパイラ自体にオーバーフローとアンダーフローの保護が組み込まれているからです。

9. 修飾子を最適化する

修飾子のコードは、修飾する関数に埋め込まれます。修飾子が使用されるたびに、そのコードが複製され、バイトコードのサイズが増え、ガスの消費量が増加します。修飾子のガスコストを最適化する方法の一つは次のとおりです:

最適化前:

最適化後:

この例では、修正を行い、修飾子で再利用できる内部関数_checkOwner()にロジックを再構築することにより、バイトコードサイズが削減され、ガスコストが低減されます。

10. ショートサーキット最適化

||(または)および&&(および)演算子の場合、論理演算はショートサーキット評価で行われます。これは、最初の条件が論理式の結果を決定するのに十分な場合、2番目の条件は評価されません。

ガス消費を最適化するためには、計算コストの低い条件を最初に配置し、可能性のある高価な計算をスキップできるようにする必要があります。

一般的な推奨事項

1. 未使用のコードを削除する

契約に未使用の関数や変数がある場合は、それらを削除することをお勧めします。これは契約のデプロイメントコストを削減し、契約のサイズを小さく保つための最も直接的な方法です。

以下はいくつかの実用的な提案です:

計算には最も効率的なアルゴリズムを使用してください。契約が特定の計算結果を直接使用する場合、不要な計算を取り除く必要があります。基本的に、未使用の計算は削除されるべきです。イーサリアムでは、開発者はストレージスペースを解放することでガスの報酬を受け取ることができます。変数がもはや必要ない場合は、削除キーワードを使用するか、そのデフォルト値に設定する必要があります。

ループの最適化:高コストのループ操作を避け、ループを統合し、繰り返し計算をループの本体から移動させてください。

2. 事前コンパイルされた契約の使用

プリコンパイル済みのコントラクトは、暗号化やハッシュ操作などの複雑なライブラリ機能を提供します。コードはEVM上で実行されるのではなく、クライアントノードでローカルに実行されるため、より少ないガスが必要です。プリコンパイル済みのコントラクトを使用すると、スマートコントラクトの実行に必要な計算作業量を減らすことでガスを節約することができます。

事前にコンパイルされた契約の例には、楕円曲線デジタル署名アルゴリズム(ECDSA)やSHA2-256ハッシュアルゴリズムが含まれます。これらの事前にコンパイルされた契約をスマートコントラクトで使用することで、開発者はガスコストを削減し、アプリケーションの効率を向上させることができます。

Ethereumネットワークでサポートされている事前コンパイル済み契約の完全なリストについては、このリンク[4]を参照してください。

3. インラインアセンブリの使用

インラインアセンブリは、高価なSolidityオペコードを使用せずにEVMによって直接実行される、低レベルで効率的なコードを開発者が記述することを可能にします。インラインアセンブリは、メモリとストレージの使用に対してより正確な制御も可能であり、さらにガスコストを削減します。さらに、インラインアセンブリはSolidity単体では実装が困難な複雑な操作を実行することもでき、ガス消費の最適化に対してより柔軟性を提供します。

ガスを節約するためにインラインアセンブリを使用する例を示します:

上記の例で見られるように、インラインアセンブリを使用する2番目のケースは、標準のケースと比較してガス効率が高いです。

ただし、インラインアセンブリを使用することはリスクをもたらす可能性があり、エラーが発生する可能性もあります。そのため、慎重に使用し、経験豊富な開発者にのみ推奨されます。

4. レイヤー2ソリューションの使用

Layer 2ソリューションは、Ethereumメインネット上で保存および計算する必要があるデータ量を削減することができます。

ロールアップ、サイドチェーン、およびステートチャネルなどのレイヤー2ソリューションは、主要なイーサリアムチェーンからトランザクション処理をオフロードし、より高速かつ安価なトランザクションを可能にします。

これらのソリューションは、大量のトランザクションをまとめることによって、オンチェーンのトランザクション数を減らし、それによってガス料金を低く抑えることができます。Layer 2のソリューションを使用することで、Ethereumのスケーラビリティが向上し、過負荷による混雑を引き起こすことなく、より多くのユーザーとアプリケーションがネットワークに参加できるようになります。

5. 最適化ツールとライブラリの使用

いくつかの最適化ツールが利用可能です。solcオプティマイザー、Truffleのビルドオプティマイザー、およびRemixのSolidityコンパイラなどがあります。

これらのツールは、バイトコードのサイズを最小化し、未使用のコードを削除し、スマートコントラクトの実行に必要な操作の数を減らすのに役立ちます。 「solmate」などの他のGas最適化ライブラリと組み合わせることで、開発者は効果的にGasコストを削減し、スマートコントラクトの効率を改善することができます。

結論

ガス消費の最適化は、開発者にとって重要なステップです。なぜなら、これによりトランザクションコストを最小化し、EVM互換ネットワーク上のスマートコントラクトの効率を向上させることができるからです。費用削減の操作を優先し、ストレージ使用量を減らし、インラインアセンブリを活用し、本記事で説明されている他のベストプラクティスに従うことで、開発者は契約のガス消費を効果的に低下させることができます。

ただし、最適化プロセス中には、開発者が注意を払い、セキュリティの脆弱性を導入しないよう注意する必要があります。コードの最適化とガス消費の削減の過程で、スマートコントラクトの固有のセキュリティが決して危険にさらされてはなりません。

[1]https://ethereum.org/en/developers/docs/gas/
[2] https://ethereum.github.io/yellowpaper/paper.pdf
[3]https://www.evm.codes/
[4] https://www.evm.codes/precompiled

免責事項:

  1. この記事は[から転載されましたPANewslab]. The copyright belongs to the original author [CertiK].転載に異議がある場合は、ゲートラーンチームは、関連手続きに従ってできるだけ早く対処します。
  2. 免責事項:この記事で表現されている見解や意見は、著者個人の見解を表しており、投資勧誘とはなりません。
  3. その他の言語版は、ゲートの学習チームによって翻訳されています。特に明記されていない限り、翻訳された記事は複製、配布、盗作することはできません。
今すぐ始める
登録して、
$100
のボーナスを獲得しよう!