カンクンのアップグレードが間もなく到来しますが、注意すべき点や潜在的なリスクは何ですか?
執筆:Salus Insights
長話を短く言うと:カンクンアップグレードが近づいており、今回のアップグレードには主に6つのEIPが提案した実行層の変更が含まれています。EIP-1153、EIP-4788、EIP-4844、EIP-5656、EIP-6780、EIP-7516です。EIP-4844は今回のアップグレードの主役であり、Ethereumのスケーラビリティを向上させ、L2の取引コストを削減し、取引速度を向上させることを目的としています。カンクンアップグレードは、1月17日、1月30日、2月7日にEthereumのGoerli、Sepolia、Holeskyテストネットでアップグレードが完了し、3月13日にEthereumメインネットでのアクティベーションが予定されています。アップグレード前に、Salusは今回のアップグレードに関する重要なセキュリティ注意事項を整理し、開発者が自己点検できるようにしました。
EIP提案の振り返り
EIP-1153
EIP-1153は、一時的なストレージオペコードを導入します。これらのオペコードは状態を操作するために使用され、その動作はストレージとほぼ同じですが、各取引の終了後に一時的なストレージは破棄されます。これは、一時的なストレージがストレージから値を逆シリアル化せず、値をストレージにシリアル化しないことを意味します。したがって、ディスクアクセスが不要なため、一時的なストレージのコストは低くなります。2つの新しいオペコードTLOADとTSTORE(「T」は「一時」を意味します)を通じて、スマートコントラクトは一時的なストレージにアクセスできます。この提案は、Ethereumの取引実行における複数のネストされた実行フレームワーク間の通信のための専用かつ効率的なソリューションを提供することを目的としています。
EIP-4788
EIP-4788は、信号チェーンブロックのハッシュツリーのルートをEVMに公開し、スマートコントラクト内部でこれらのルートにアクセスできるようにすることを目的としています。これにより、コンセンサス層の状態に信頼なしでアクセスでき、ステーキングプール、リステーキング構造、スマートコントラクトブリッジ、MEV緩和などのさまざまなユースケースをサポートします。この提案は、これらのルートをスマートコントラクトに保存し、リングバッファを使用してストレージ消費を制限し、各実行ブロックがこれらの情報を表現するために定数のスペースのみを必要とすることを保証します。
EIP-4844
EIP-4844は、「シャーディングBlobトランザクション」と呼ばれる新しいトランザクションフォーマットを導入し、Ethereumのデータ可用性をシンプルで前方互換性のある方法で拡張することを目的としています。この提案は、EVM実行アクセスができない大量のデータを含む「blob-carrying transactions」を導入し、その約束にアクセスできるようにします。このフォーマットは、将来の完全シャーディング使用のフォーマットと完全に互換性があり、ロールアップによるスケーリングに一時的だが顕著な緩和を提供します。
EIP-5656
EIP-5656は、高効率でメモリ領域をコピーするための新しいEVM命令MCOPYを導入します。この提案は、EVM上でのメモリコピー操作のオーバーヘッドを削減することを目的としており、MCOPY命令を通じてメモリ間のデータコピーを直接実現します。MCOPYは、ソースアドレスとターゲットアドレスが重複することを許可し、後方互換性を考慮して設計されており、データ構造の構築、メモリオブジェクトの効率的なアクセスとコピーを含むさまざまなシナリオの実行効率を向上させることを目指しています。
EIP-6780
EIP-6780は、SELFDESTRUCTオペコードの機能を変更しました。この提案では、SELFDESTRUCTは契約作成と同じ取引内でのみアカウントを削除し、すべてのEtherを転送します。それ以外の場合、SELFDESTRUCTを実行しても契約は削除されず、すべてのEtherが指定されたターゲットに転送されるだけです。この変更は、将来のVerkleツリーの使用に適応するためであり、EVMの実装を簡素化し、状態変化の複雑さを減少させることを目的とし、SELFDESTRUCTの一部の一般的なシナリオを保持します。
EIP-7516
EIP-7516は、新しいEVM命令BLOBBASEFEEを導入し、現在のブロック実行中のblob基本料金値を返します。この命令はEIP-3198のBASEFEEオペコードに似ていますが、EIP-4844で定義されたblob基本料金を返す点が異なります。この機能により、コントラクトはプログラム的にblobデータのガス価格を考慮できるようになり、たとえば、ロールアップコントラクトが信頼なしにblobデータの使用コストを計算したり、これに基づいてblobガス先物を実装したりして、blobデータコストを平滑化することが可能になります。
公式に開示されたセキュリティ考慮事項
EIP-1153
スマートコントラクト開発者は、一時的ストレージ変数のライフサイクルを使用前に理解する必要があります。一時的ストレージは取引終了時に自動的にクリアされるため、スマートコントラクト開発者はガスを節約するために呼び出し中にスロットをクリアしないように試みるかもしれません。しかし、これは同じトランザクション内で契約とのさらなる相互作用を妨げる可能性がある(たとえば、再入ロックの場合)か、他のエラーを引き起こす可能性があるため、スマートコントラクト開発者は注意し、一時的ストレージスロットが保持されている場合にのみ非ゼロ値を保持するようにすべきです。SSTORE以外では、これらのオペコードの動作はSLOADと完全に同じであるため、すべての一般的なセキュリティ注意事項が適用され、特に再入リスクに関しては注意が必要です。
スマートコントラクト開発者は、一時的ストレージをメモリマッピングの代替手段として使用しようとするかもしれません。彼らは、呼び出しが戻るか復元されるとき、一時的ストレージはメモリのように破棄されないことを認識し、これらのユースケースではメモリを優先する必要があります。同じトランザクション内での再入時に予期しない動作を引き起こさないようにするためです。一時的ストレージのメモリ上のコストは必然的に高く、この使用パターンを防ぐべきです。メモリ上のマッピングのほとんどの使用法は、キーでソートされたエントリーリストを通じてより良く実現でき、スマートコントラクト内でメモリ上のマッピングが必要なケースはほとんどありません(つまり、著者は生産中に知られているユースケースがないことを知っています)。
EIP-4844
このEIPは、各信号ブロックの帯域幅要件を最大約0.75MB増加させます。これは、現在のブロックの理論的最大サイズ(30Mガス/各calldataバイト16ガス=1.875Mバイト)よりも40%大きいため、最悪のケースでの帯域幅を大幅に増加させることはありません。マージ後、ブロック時間は静的であり、予測不可能なポアソン分布ではなく、大きなブロックの伝播に保証された時間枠を提供します。
呼び出しデータが限られていても、このEIPの持続的な負荷は、Blobストレージを実行負荷と同じくらい長く保持する必要がないため、呼び出しデータコストを削減できる代替案よりもはるかに低くなります。これにより、これらのblobを保持する必要がある戦略が可能になります。選択された具体的な値は、MINEPOCHSFORBLOBSIDECARS_REQUESTSエポックであり、約18日であり、提案された(しかしまだ実施されていない)実行有効負荷の履歴の1年のローテーション時間と比較して、遅延ははるかに短いです。
EIP-5656
クライアントは、その実装が中間バッファを使用しないことに注意する必要があります(たとえば、C stdlibmemmove関数は中間バッファを使用しません)。これは潜在的なサービス拒否(DoS)ベクトルです。バイトを移動するために使用されるほとんどの言語の組み込み関数/標準ライブラリ関数は、ここで正しいパフォーマンス特性を持っています。
それ以外にも、サービス拒否(DoS)およびメモリ枯渇攻撃の分析は、他のメモリにアクセスするオペコードと同じであり、メモリ拡張は同じ価格設定ルールに従います。
EIP-6780
以下のアプリケーションはSELFDESTRUCTによって破壊され、この方法で使用するアプリケーションはもはや安全ではありません:
WhereCREATE2は、同じ位置に契約を再展開して契約をアップグレードするために使用されます。この機能はもはやサポートされておらず、ERC-2535または他のタイプのプロキシ契約に置き換える必要があります。
契約がSELFDESTRUCTを通じてEtherを燃焼させることに依存している場合、その契約は同じ取引内で作成されていません。
スマートコントラクト関連リスク
EIP-1153
TLOADおよびTSTOREオペコードを使用する2つのシナリオを想定します:
- 呼び出される契約がそのオペコードを使用する
- 呼び出しを開始する契約がそのオペコードを使用する
リスク1:
従来のSSTOREおよびSLOADと比較して、新たに追加された一時的ストレージは主にデータのストレージ期限を変更します。tstoreに保存されたデータはtloadを通じて読み取られ、1つの取引の実行が終了するとそのデータは解放され、sstoreのように契約に永続的に記録されることはありません。開発者はこのオペコードの特性を理解し、誤った使用によってデータが契約に正しく書き込まれず損失を引き起こさないようにする必要があります。また、tstoreのデータはプライベート変数に属し、契約自体のみがアクセスできます。外部でそのデータを使用したい場合は、パラメータとして渡すか、public storage変数に一時保存する必要があります。
リスク2:
もう1つの潜在的なリスクは、スマートコントラクト開発者が一時的ストレージ変数のライフサイクルを正しく管理しない場合、データが不適切なタイミングでクリアされたり、誤って保持されたりする可能性があることです。契約がトランザクションの後続呼び出しで一時的ストレージに保存されたデータを使用することを期待しているが、これらのデータのライフサイクルを適切に管理できていない場合、異なる呼び出し間でデータが誤って共有されたり失われたりし、論理エラーやセキュリティ脆弱性を引き起こす可能性があります。Tokenプロジェクトのbalanceやallowanceデータが正しく保存されないと、契約の論理エラーが発生し、損失を引き起こす可能性があります。また、ownerアドレスを設定する際にこのオペコードを使用すると、特権アドレスが正しく記録されず、契約の重要なパラメータの変更が失われる可能性があります。
一時的ストレージを使用して、暗号通貨取引所での取引価格を一時的に記録するスマートコントラクトを考えてみましょう。この契約は、各取引が完了するたびに価格を更新し、ユーザーが短時間で最新の価格を照会できるようにします。しかし、契約設計が取引終了時に一時的ストレージが自動的にクリアされる特性を考慮していない場合、1つの取引が終了した後から次の取引が始まるまでの間に、ユーザーは誤ったまたは古い価格を得る可能性があります。これは、ユーザーが誤った情報に基づいて意思決定を行う原因となり、悪意のある利用を受け、プラットフォームの信頼性やユーザーの資産の安全性に影響を与える可能性があります。
EIP-6780
この提案は、以前のselfdestructオペコードの動作を変更し、契約を破壊せず、トークンを転送するだけで、自己破壊と同じ取引内で作成された契約のみが破壊されます。このEIPの影響は比較的大きいです。
create2を使用して同じアドレスに契約を再展開し、契約をアップグレードします。この機能はもはやサポートされておらず、ERC-2535または他のタイプのプロキシ契約に置き換える必要があります。(これは、create2を使用してアップグレード可能な契約を実装するオンチェーン契約の安全性に影響を与える可能性があります)
スマートコントラクト内のSELFDESTRUCT操作は、契約を破壊し、契約の残高を指定されたターゲットアドレスに送信することを許可します。この場合、契約はSELFDESTRUCTを使用してEtherを破壊し、破壊されたEtherを契約に送信しました。しかし、この契約は同じ取引内で作成された契約(同じ取引内でこの契約または他の契約によって作成された契約)のみです。それ以外の場合は、Etherを転送するだけで契約は破壊されません(たとえば、自己破壊し、受益者が自己破壊契約である場合、何の変更も生じません)。これは、selfdestructを使用して引き出しや他の操作を行うすべての契約に影響を与えます。
1inch CHI Tokenのようなガストークンの動作原理:オフセットを保持し、常にこのオフセットでCREATE2またはSELFDESTRUCTを実行します。この更新後、現在のオフセットの契約が正しく自己破壊されていない場合、以降のCREATE2は契約を正常に展開できません。
この提案の実施は、契約に対する直接的な攻撃を引き起こすものではありませんが、selfdestruct操作に依存する既存のデプロイされた契約の正常な論理を損なう可能性があります(資金移動のために自己破壊に依存する契約は影響を受けませんが、後続の操作が自己破壊された契約の削除を要求する場合は影響を受けます)。これは、契約が予期しない動作を引き起こし、契約やユーザーにとって、資金の損失などの危害をもたらす可能性があります(たとえば、create2を使用して元のアドレスに新しい契約をデプロイし、元の契約を自己破壊してアップグレードする契約が、もはや成功裏にデプロイできなくなる)。長期的には、オペコードの機能を変更することは、中央集権的な問題を引き起こす可能性があります。
たとえば、既存の金庫契約vaultを更新する場合:
- create2一時的ストレージ契約を使用してvaultの資金を一時的に保存
- vault契約を自己破壊し、資金を一時的契約に転送(契約は破壊されず、資金のみが転送されました)
- 元のアドレスでcreate2新しいvault契約を作成(失敗、元のvault契約が破壊されていないため)
- 一時的契約を自己破壊して資金をvaultに返す(資金損失、vault契約が作成されていない)