This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
イーサリアムスマートコントラクトGas費最適化実践ガイド
イーサリアムスマートコントラクトGas最適化実践ガイド
イーサリアム主ネットのGas費用は常に解決が難しい問題であり、特にネットワークが混雑しているときにより顕著です。ピーク時にはユーザーは高額な取引費用を支払う必要があります。したがって、スマートコントラクトの開発段階でGas費用の最適化を行うことが非常に重要です。Gas消費の最適化は、取引コストを効果的に削減するだけでなく、取引効率を向上させ、ユーザーにより経済的で効率的なブロックチェーンの使用体験を提供します。
本文では、イーサリアム仮想マシン(EVM)のGas費メカニズム、Gas費最適化の核心概念、そしてスマートコントラクト開発におけるGas費最適化のベストプラクティスについて概説します。これらの内容が開発者にインスピレーションと実用的な助けを提供し、一般ユーザーがEVMのGas費用の運用方法をより良く理解し、ブロックチェーンエコシステムの課題に共に対処する手助けになることを願っています。
EVMのGas料金メカニズムの概要
EVMに互換性のあるネットワークでは、「Gas」は特定の操作を実行するために必要な計算能力を測定する単位です。
EVMの構造レイアウトでは、Gas消費は3つの部分に分かれています:操作の実行、外部メッセージの呼び出し、そしてメモリとストレージの読み書き。
各取引の実行には計算リソースが必要なため、無限ループや拒否サービス(DoS)攻撃を防ぐために一定の手数料が徴収されます。取引を完了するのに必要な手数料は「Gas費」と呼ばれます。
EIP-1559(ロンドンハードフォーク)が有効になって以来、Gas料金は以下の式で計算されます:
ガス料金 = 使用されたガスの単位 * (基本料金 + プライオリティ料金)
基本料金は消失し、優先料金はインセンティブとして機能し、検証者が取引をブロックチェーンに追加することを促します。取引を送信する際に優先料金を高く設定することで、取引が次のブロックに含まれる可能性が高まります。これは、ユーザーが検証者に支払う「チップ」のようなものです。
EVM でのガス最適化の理解
Solidityでスマートコントラクトをコンパイルすると、コントラクトは一連の「操作コード」、つまりopcodesに変換されます。
いかなる操作コード(も、たとえば契約の作成、メッセージ呼び出しの実行、アカウントストレージへのアクセス、仮想マシン上での操作の実行)には、認められたGas消費コストがあり、これらのコストはイーサリアムのホワイトペーパーに記録されています。
複数回のEIPの修正を経て、その中のいくつかのオペコードのGasコストが調整され、黄皮書にあるものと若干の相違がある可能性があります。
ガス最適化の基本概念
Gasの最適化の核心理念は、EVMブロックチェーン上でコスト効率の高い操作を優先的に選択し、Gasコストが高い操作を避けることです。
EVMでは、以下の操作のコストが比較的低いです:
コストの高い操作には次のものが含まれます:
EVMガス費用最適化のベストプラクティス
上記の基本概念に基づき、私たちは開発者コミュニティのためにGas費用最適化のベストプラクティスリストを整理しました。これらのプラクティスに従うことで、開発者はスマートコントラクトのGas費用消費を削減し、取引コストを下げ、より効率的でユーザーフレンドリーなアプリケーションを構築できます。
1. ストレージの使用をできるだけ減らす
Solidityでは、Storage(ストレージ)は限られたリソースであり、そのGas消費はMemory(メモリ)よりもはるかに高いです。スマートコントラクトがストレージからデータを読み取ったり書き込んだりするたびに、高額なGasコストが発生します。
イーサリアムのホワイトペーパーの定義によれば、ストレージ操作のコストはメモリ操作の100倍以上高い。例えば、OPcodeのmloadとmstore命令はそれぞれ3ガスユニットしか消費しないが、ストレージ操作であるsloadとsstoreは、最も理想的な状況であっても、コストは少なくとも100ユニット必要である。
制限されたストレージ使用方法には、
! イーサリアムスマートコントラクトのガス最適化のためのトップ10のベストプラクティス
2. 変数パッケージ
スマートコントラクト中使用されるStorage slot(ストレージスロット)の数および開発者がデータを表示する方法は、Gas費の消費に大きな影響を与えます。
Solidityコンパイラは、コンパイルプロセス中に連続するストレージ変数をパッキングし、32バイトのストレージスロットを変数ストレージの基本単位として使用します。変数のパッキングとは、変数を合理的に配置することで、複数の変数が単一のストレージスロットに適合できるようにすることを指します。
この詳細な調整により、開発者は20,000ガス単位を節約できます(未使用のストレージスロットを保存するには20,000ガス)が必要ですが、現在は2つのストレージスロットのみが必要です。
各ストレージスロットはガスを消費するため、変数のパッキングは必要なストレージスロットの数を減らすことでガスの使用を最適化します。
! [イーサリアムスマートコントラクトのガス最適化のためのトップ10のベストプラクティス](https://img-cdn.gateio.im/webp-social/moments-995905cb414526d4d991899d0c2e6443.webp0192837465674839201
) 3. データ型の最適化
変数はさまざまなデータ型で表すことができますが、異なるデータ型に対応する操作コストは異なります。適切なデータ型を選択することで、Gasの使用を最適化するのに役立ちます。
例えば、Solidityでは、整数は異なるサイズに細分化されます:uint8、uint16、uint32など。EVMが256ビット単位で操作を実行するため、uint8を使用すると、EVMは最初にそれをuint256に変換する必要があり、この変換は追加のガスを消費します。
単独では、uint256を使用する方がuint8よりも安価です。しかし、変数のパッキング最適化を使用すると異なります。もし開発者が4つのuint8変数を1つのストレージスロットにパッキングできるなら、それらを反復処理する総コストは4つのuint256変数よりも低くなります。これにより、スマートコントラクトは1回のストレージスロットの読み書きを行い、1つの操作で4つのuint8変数をメモリ/ストレージに配置できるようになります。
! [イーサリアムスマートコントラクトのガス最適化のためのトップ10のベストプラクティス]###https://img-cdn.gateio.im/webp-social/moments-55fcdb765912ef9cd238c46b1d248cff.webp(
) 4. 固定サイズの変数を動的変数の代わりに使用する
データが32バイト以内に制御できる場合は、bytesまたはstringsの代わりにbytes32データ型を使用することをお勧めします。一般的に、固定サイズの変数は可変サイズの変数よりもガス消費が少なくなります。バイトの長さを制限できる場合は、できるだけbytes1からbytes32の最小長を選択してください。
5. マッピングと配列
Solidityのデータリストは、2つのデータ型で表すことができます: 配列###Arrays(とマッピング)Mappings(ですが、それらの構文と構造は全く異なります。
マッピングは大多数のケースで効率が高く、コストが低いですが、配列は反復可能でデータ型のパッキングをサポートします。したがって、データリストの管理においては、反復が必要な場合やデータ型のパッキングによってGas消費を最適化できる場合を除いて、マッピングを優先して使用することをお勧めします。
! [イーサリアムスマートコントラクトのガス最適化のためのトップ10ベストプラクティス])https://img-cdn.gateio.im/webp-social/moments-5f3d7e103e47c886f50599cffe35c707.webp(
) 6. メモリの代わりに calldata を使用する
関数の引数で宣言された変数は、calldataまたはmemoryに格納できます。両者の主な違いは、memoryは関数によって変更可能であるのに対し、calldataは不変であることです。
この原則を覚えておいてください: 関数の引数が読み取り専用の場合は、memoryではなくcalldataを優先的に使用すべきです。これにより、関数のcalldataからmemoryへの不要なコピー操作を回避できます。
7. 可能な限り Constant/Immutable キーワードを使用してください
Constant/Immutable変数は契約のストレージには保存されません。これらの変数はコンパイル時に計算され、契約のバイトコードに保存されます。したがって、ストレージと比較して、それらのアクセスコストははるかに低くなります。できる限りConstantまたはImmutableキーワードを使用することをお勧めします。
![イーサリアムスマートコントラクトのGas最適化トップ10ベストプラクティス]###https://img-cdn.gateio.im/webp-social/moments-9c566626ab499ef65d6f5089a2876ad3.webp(
) 8. オーバーフロー/アンダーフローが発生しないことを確認してUncheckedを使用する
開発者が算術演算がオーバーフローまたはアンダーフローを引き起こさないことを確認できる場合、Solidity v0.8.0で導入されたuncheckedキーワードを使用して、余分なオーバーフローまたはアンダーフローのチェックを回避し、Gasコストを節約することができます。
さらに、0.8.0以上のバージョンのコンパイラではSafeMathライブラリを使用する必要がなくなりました。なぜなら、コンパイラ自体にオーバーフローおよびアンダーフロー保護機能が組み込まれているからです。
9. 最適化モディファイア
修正プログラムのコードは修正された関数に埋め込まれており、修正プログラムを使用するたびに、そのコードがコピーされます。これにより、バイトコードのサイズが増加し、ガス消費が増加します。
内部関数_checkOwner###(にロジックを再構成することで、修飾子内でこの内部関数を再利用可能にし、バイトコードのサイズを削減し、ガスコストを低減できます。
![イーサリアムスマートコントラクトのGas最適化トップ10のベストプラクティス])https://img-cdn.gateio.im/webp-social/moments-c0701f9e09280a1667495d54e262dd2f.webp(
) 10. ショートサーキット最適化
||および&&演算子に対して、論理演算はショートサーキット評価が行われます。すなわち、最初の条件が論理式の結果を決定できる場合、2番目の条件は評価されません。
Gas消費を最適化するためには、計算コストが低い条件を前に置くべきです。そうすることで、高コストの計算をスキップできる可能性があります。
! [イーサリアムスマートコントラクトのガス最適化のためのトップ10のベストプラクティス]###https://img-cdn.gateio.im/webp-social/moments-a823fb7761aafa6529a6c45304e0314b.webp(
一般的なアドバイスを追加する
) 1. 不要なコードを削除する
コントラクトに未使用の関数や変数が存在する場合は、削除することをお勧めします。これは、コントラクトのデプロイコストを削減し、コントラクトのサイズを小さく保つための最も直接的な方法です。
以下は実用的なアドバイスです:
最も効率的なアルゴリズムを使用して計算を行います。契約内で特定の計算結果を直接使用する場合は、これらの冗長な計算プロセスを削除する必要があります。本質的に、使用されていない計算は削除されるべきです。
イーサリアムでは、開発者はストレージを解放することでガス報酬を得ることができます。もし特定の変数が不要になった場合は、deleteキーワードを使用して削除するか、デフォルト値に設定する必要があります。
ループ最適化: 高コストのループ操作を避け、可能な限りループを統合し、繰り返し計算をループ本体の外に移動させる。
![イーサリアムスマートコントラクトのGas最適化のトップ10ベストプラクティス]###https://img-cdn.gateio.im/webp-social/moments-839b91e2f02389949aa698d460a497d8.webp(
) 2. プレコンパイルコントラクトの使用
プリコンパイルされたコントラクトは、暗号化やハッシュ操作などの複雑なライブラリ関数を提供します。コードはEVM上ではなく、クライアントノードのローカルで実行されるため、必要なガスが少なくなります。プリコンパイルされたコントラクトを使用することで、スマートコントラクトの実行に必要な計算負荷を削減し、ガスを節約できます。
プレコンパイルされたコントラクトの例には、楕円曲線デジタル署名アルゴリズム###ECDSA(およびSHA2-256ハッシュアルゴリズムが含まれます。スマートコントラクト内でこれらのプレコンパイルされたコントラクトを使用することにより、開発者はガスコストを削減し、アプリケーションの実行効率を向上させることができます。
) 3. インラインアセンブリコードを使用する
インラインアセンブリ###in-line assembly(は、開発者がEVMによって直接実行可能な低レベルで効率的なコードを書くことを可能にし、高価なSolidityオペコードを使用する必要がありません。インラインアセンブリは、メモリとストレージの使用をより正確に制御できるため、Gas費をさらに削減します。さらに、インラインアセンブリは、Solidityのみでは実現が難しい複雑な操作を実行でき、Gas消費を最適化するための柔軟性を提供します。
しかし、インラインアセンブリを使用することはリスクをもたらし、間違いやすくなる可能性があります。したがって、注意して使用し、経験豊富な開発者の操作に限るべきです。
![イーサリアムスマートコントラクトのGas最適化トップ10ベストプラクティス])
この文章に対して中国語でコメントを生成してください。