暗号プロジェクトのスマートコントラクトを監査するためのステップバイステップガイド

スマートコントラクト監査とは、契約が失敗したり、悪用されたり、ユーザーが想定していない方法で制御されたりする可能性のある状況を体系的に調査するものです。これは、単にスキャナーを実行したり、監査バッジを読み取ったり、ソースコードが検証済みであることを確認したりするのとは異なります。重要な資金を投入する前に、以下のワークフローを使用して、デプロイ済みのEVMコントラクトまたはコードベースをレビューしてください。

重要:これは実用的なレビューフレームワークであり、プロジェクトの安全性を保証するものではなく、投資アドバイスでもありません。相当な価値を持つ本番環境プロトコルは、経験豊富なセキュリティ専門家による独立したレビューを受けるべきです。このガイドに掲載されているインターフェーススタイルの画像は例示であり、特定のプロジェクトや展開に関する証拠として扱うべきではありません。

監査チェックリストの概要

ステップ主な質問有用な証拠
1. 適用範囲ユーザーが実際に使用している契約書を正確に確認しているだろうか?アドレス、チェーン、バイトコード、プロキシ、実装
2. エントリーポイント発信者はそれぞれ何ができるのか?公開/外部関数、状態変化、呼び出しグラフ
3. 自動化注目すべき明白なパターンとは何でしょうか?コンパイラ出力、Slitherの検出結果、検出器のトリアージ
4. 手動セキュリティ一連の呼び出しによって、前提条件が覆される可能性はあるか?外部呼び出し、再入可能性、コールバック、障害処理
5. 論理例外的なケースにおいても、会計処理は正しいまま維持されるのか?算術演算、丸め処理、手数料、制限、状態遷移
6. 特権誰がシステムを変更したり停止させたりできるのか?役割、所有者、管理者キー、プロキシ、初期化子
7. テスト予期せぬ入力やシーケンスに対しても、その挙動は維持されるのか?ユニットテスト、ファジングテスト、不変条件テスト、フォークテスト
8. 報告他の人が同じ結果を再現して再検証することは可能でしょうか?発見、影響、証拠、修正および再テストの状況

ステップ1:スコープとデプロイされた成果物を確認する

イーサリアムメインネット、コントラクトアドレス、コンパイラバージョン、検証済みソースステータス、および正確なバイトコード一致を示す一般的なコントラクト検証画面
分析前に記録するネットワーク、アドレス、コンパイラバージョン、バイトコード一致チェックを示す契約検証ビュー。

正確なチェーンとアドレスから始めましょう。デプロイメントアドレス、トランザクションハッシュ、ブロック番号、コンパイラバージョン、オプティマイザ設定、コンストラクタ引数、そしてチームがデプロイ済みとしているコミットまたはリリースを記録します。プロジェクトによっては、トークン、ルーター、ボールト、プロキシ、実装、オラクル、テストデプロイメント用に複数のアドレスが存在する場合があります。誤ったアドレスを確認しても、実質的な価値はありません。

エクスプローラーで検証したソースが、デプロイされたバイトコードを再現しているかどうかを確認します。検証は、ソースと ABI を検査できるため便利ですが、これは単なる識別チェックであり、ビジネスロジックが安全であることを証明するものではありません。コントラクトがアップグレード可能な場合は、プロキシとその現在の実装の両方を特定します。プロキシのドキュメント化されたメカニズムまたはエクスプローラー情報から実装アドレスを読み取り、その実装がレビューしようとしている実装であることを確認します。Etherscan の公式 Foundry 検証ガイドには、新規および既存のコントラクトの検証方法が記載されています。

また、境界を明確に定義してください。インポートされたライブラリ、継承されたコントラクト、リンクされたライブラリ、デプロイされたヘルパーコントラクト、オラクルアダプタ、ユーザーから受け取ったトークン、および特権を持つオフチェーンコンポーネントを含めてください。範囲外の項目とその理由を明記してください。これにより、限定的なレビューがシステム全体のレビューと誤解されることを防ぎます。

ステップ2:エントリーポイントとアセットマップを作成する

ERC-20 スタイルのコントラクト実装の横に、公開および外部の Solidity 関数を一覧表示する汎用ソース レビュー ウィンドウ
レビュー担当者が状態変化を追跡する前に、公開エントリポイントと外部エントリポイントを分離する関数インベントリ。

継承関数、フォールバックハンドラ、受信ハンドラを含む、すべての公開関数と外部関数をリストアップします。それぞれの関数について、以下のことが可能かどうかを記録します。

  • 現地通貨またはトークンを移動する。
  • 造幣、焼却、借用、清算、または会計の改ざん。
  • オラクル、料金、制限、役割、一時停止状態、または実装を変更する。
  • 外部呼び出し、委任呼び出し、または低レベル呼び出しを行う。
  • 別の状態変化関数が依存するデータを読み込む。

次に、資産と信頼境界をマッピングします。ユーザーからストレージへの入金から、価格設定とシェア計算を経て、引き出しに至るまでの流れを追跡します。呼び出し元から提供されたすべてのアドレスと、ストレージからロードされたすべてのアドレスを特定します。オラクル、トークン、ブリッジメッセージ、キーパー、コールバックレシーバー、管理者など、どの値が正直であると想定されているかを尋ねます。最も価値の高いレビュー対象は、ユーザー制御入力、特権状態、算術演算、および外部呼び出しを組み合わせた関数です。

ステップ3:クリーンコンパイルして静的解析を実行する

コマンド「slither dot」と、再入可能性、未チェックの低レベル呼び出し、およびERC-20インターフェースの問題に関する検出結果を表示する汎用ターミナル
静的解析を実行すると、潜在的な問題点を迅速に特定できますが、それらは実際のコードと脅威モデルに基づいて確認する必要があります。

プロジェクトのビルドを、指定された Solidity バージョン、依存関係のバージョン、オプティマイザ構成、およびターゲットチェーンの前提条件に基づいて再現してください。コンパイラの警告は、無害なノイズではなく、レビュー項目として扱ってください。Solidity のセキュリティに関する考慮事項では、警告を真剣に受け止め、コントラクトを分かりやすく保ち、既知のコンパイラの問題を確認することを特に推奨しています。コンパイラのバージョンや影響を受けるコードパターンが関連する場合は、Solidity コンパイラの既知のバグに関する公式リストを参照してください。

Hardhat、Foundry、または同様のプロジェクトの場合、プロジェクトのルートディレクトリからSlitherを実行します。公式ドキュメントでは、このツールはSolidityおよびVyperの静的解析ツールとして説明されており、共通のコマンドが示されています。

slither .

出力を保存し、影響度と信頼度に基づいて各結果をトリアージします。任意のトークン送信、保護されていないアップグレード、再入可能性、チェックされていない戻り値、危険なデリゲートコール、tx.origin、弱い乱数性、および不適切なインターフェースに関する検出結果を注意深く確認してください。検出器は誤検出を報告したり、プロジェクト固有の経済的欠陥を見逃したり、他の場所で意図的に制約されているコードにフラグを立てたりする可能性があります。静的解析は検索範囲を絞り込むものであり、手動による推論に取って代わるものではありません。Slitherリポジトリとドキュメントには、レビューを整理するのに役立つエントリポイント、認証、コールグラフ、および契約概要のプリンタも記載されています。

ステップ4:外部呼び出しと再入可能性を手動で追跡する

残高更新前の低レベル値呼び出しと重大度の高い再入可能性レビューノートを強調表示する汎用コードレビューウィンドウ
残高更新の前に外部呼び出しが強調表示されており、レビュー担当者がすべての引き出し経路で確認すべき順序に関する疑問点を示しています。

外部呼び出しごとに、呼び出し前、呼び出し中、呼び出し後の状態を停止してトレースします。呼び出し先は、悪意のあるコントラクト、フック付きトークン、コールバックレシーバー、または共有依存関係を変更する別のプロトコルである可能性があります。Solidity のドキュメントでは、別のコントラクトとのやり取りによって制御がそのコントラクトに渡される可能性があることを説明し、チェック - 効果 - 相互作用のパターンを推奨しています。つまり、最初に検証を行い、次にこのコントラクトの状態を更新し、最後に外部とのやり取りを行うという手順です。

検索対象を明白なイーサリアム送金だけに限定しないでください。ERC-777 スタイルのフック、ERC-1155 コールバック、フラッシュローンコールバック、任意のルーター、オラクル呼び出し、および継承ライブラリを介して行われる呼び出しを確認してください。関数間およびコントラクト間の再入可能性を確認してください。コールバックが中間状態を読み取る別の関数に入る可能性があります。すべての低レベル呼び出しが成功結果をチェックし、戻り値を正しく処理していることを確認してください。失敗した受取人が引き出しやループを永久にブロックできるかどうかを尋ねてください。

考えられるすべての問題に対して、具体的な攻撃手順を記録してください。例えば、攻撃者が入金し、出金を開始し、コールバックを受け取り、2回目の出金を再度実行し、その後初めて最初の呼び出しを完了させる、といった手順です。特定の不変条件やガードのために手順が機能しない場合は、その理由を書き留めてください。これにより、結論が推測ではなく、監査可能なものになります。

ステップ5:算術不変条件とビジネス不変条件をテストする

整数範囲、丸め、株価計算、ゼロ値のエッジケースのチェックを示す一般的な監査チェックリスト
算術演算とビジネスロジックのチェックリストは、通常の正常系テストでは見落とされがちなエッジケースを明確に示します。

単位と換算の意味を必ず確認してください。weiとether、トークンの小数点、ベーシスポイント、株式と資産、符号付き値、時間単位などです。丸めの方向に従ってください。預金者、借入者、清算人、または手数料受取人に有利なように丸められる除算は、繰り返されると価値が漏洩する可能性があります。除算の前に乗算、最小金額と最大金額、手数料の上限、古い価格、供給ゼロ、残高ゼロ、最初の預金者または最後の引き出し者を確認してください。

Solidity 0.8以降では、通常、算術オーバーフローとアンダーフローが検出されますが、uncheckedブロック内のコードは意図的にその動作を変更します。チェックされた算術演算は、制限が正しく設計されていない場合、プロトコルをロールバックさせたり、使用不能にしたりする可能性もあります。盗難や不正会計、および処理不可能な値によって引き起こされるサービス拒否という、両方の結果をテストしてください。

不変条件をテストにする前に、平易な言葉で記述してください。例としては、「総株式数は、規定の丸めルールに基づく資産に対応する」、「ユーザーは、記録された請求額を超える金額を引き出すことはできない」、「トークンの総供給量は、そのモデルが適用される残高の合計に等しい」、「手数料は、設定された上限を超えることはできない」などがあります。トークンはコントラクトに直接送信される場合や、想定されるERC-20実装とは異なる動作をする可能性があるため、ストレージ残高と実際のトークン残高を比較してください。

ステップ6:権限とアップグレード可能性を確認する

所有者、管理者、一時停止者、アップグレード者の役割とプロキシと実装の関係を示す、一般的な権限とアップグレード可能性の画面
権限レビューでは、各役割をそのアドレス、許可されたアクション、転送プロセス、およびアップグレードパスに関連付ける必要があります。

権限マトリックスを作成します。すべての管理機能について、必要な役割、現在の所有者、転送メカニズム、遅延、マルチシグネチャまたはガバナンス制御、および緊急時の動作を特定します。特に、トークンの発行、一時停止、手数料の変更、オラクルソースの変更、資金の復旧、コードのアップグレード、および信頼できるトークンまたはルーターアドレスの変更に注意してください。OpenZeppelinのアクセス制御に関するドキュメントでは、単純な所有権と役割ベースの権限を区別し、最小権限を有用なセキュリティ対策として説明しています。

「コードによって管理者がこれを実行できる」という点と「任意のユーザーがこれを実行できる」という点を区別してください。前者は明確なガバナンスまたは管理上のリスクとなる可能性があり、後者は認証の脆弱性です。ロールチェックが、公開関数からアクセスできる内部ヘルパーを含む、すべての機密性の高いパスを網羅していることを確認してください。デフォルトの管理者が自身または他のユーザーに追加の権限を付与できるかどうか、また所有権の移転が誤って使用できないアドレスに送信される可能性があるかどうかを確認してください。

プロキシについては、初期化子、実装認証、アップグレード遅延、ストレージレイアウト、ロールバックまたは緊急時対応計画を確認してください。OpenZeppelinのアップグレード可能なコントラクトに関するガイダンスでは、コンストラクタがプロキシストレージを初期化しない理由、初期化子を保護する必要がある理由、実装を初期化せずに放置してはならない理由、ストレージの順序やタイプを変更するとアップグレードが破損する可能性がある理由について説明しています。プロキシ管理者キーは、実装の詳細ではなく、プロトコルのセキュリティ境界の一部として扱ってください。

ステップ7:ファジング、不変条件、フォークを用いてシステムをテストする

合格したファズテスト、合格した不変条件テスト、および反例呼び出しシーケンスを表示する汎用テストダッシュボード
通過キャンペーンは有用な証拠となる一方、反例トレースはどのシーケンスを調査する必要があるかを正確に示す。

期待される動作を確認するための単体テストを実行した後、不正な呼び出し、ゼロ値、最大値、期限切れの署名、古いOracleデータ、転送失敗、および繰り返し操作に対するネガティブテストを追加します。少数の数値のみをテストするのではなく、入力に対してファジングテストを実施します。設計上コールバックが可能な場合は、複数のアクターと悪意のある受信コントラクトを含めます。

多数のランダムな呼び出し後も真であり続ける必要があるプロパティには、不変条件テストを使用してください。Foundryの不変条件テストに関するドキュメントには、ランダムなシーケンス、ファジングされた入力、実行、深度、ターゲットコントラクト、およびターゲット送信者について説明されています。呼び出しが意味を持つようにハンドラを設定してください。テストアクターがトークンを持っていないためにファジングされたすべてのデポジットが元に戻る場合、不変条件が合格したとしても、有用な状態が何も変化しなかったことを意味するだけかもしれません。

可能な場合は、ターゲットネットワークのフォークを使用して、デプロイされたアドレス、現在の構成、トークンの動作、およびプロキシルーティングを検証してください。独立したローカルフォークを使用する場合を除き、フォークテストは安全かつ読み取り専用にしてください。失敗したシーケンスはすべて最小限に抑え、反例、呼び出し元アドレス、ブロックコンテキスト、残高、および関連するストレージ値を保持してください。テストが合格したとしても、それはテストされたパスに関する証拠であって、すべての可能なパスの証明ではありません。

ステップ8:修正および再テスト可能な所見を記述する

重大度別の調査結果、未解決、修正済み、許容リスクの状態、および再テストチェックリストを示す一般的な監査レポート
有用な報告書は、重症度と状態を証拠、具体的な解決策、および再検査条件と関連付けている。

問題ごとに1つの記録を使用してください。実務上の所見には以下を含める必要があります。

  • タイトルと場所:契約、機能、ファイル、行またはコードの参照。
  • 影響:盗難、凍結、水増し、迂回、または誤りを生じる可能性のあるもの。
  • 前提条件:必要な権限、残高、タイミング、または構成。
  • 再現:短いトランザクションシーケンス、テスト、トレース、または証明。
  • 推奨事項:トレードオフを考慮した上で、具体的なコードまたは運用上の変更を行う。
  • ステータス:未解決、修正済み、軽減済み、リスク許容、または再現不能。
  • 再検査:解決を確認するための、全く同じ検査または観察。

深刻度は、コードパターンの見た目の危険性ではなく、現実的な影響と悪用可能性を反映するべきです。前提条件を説明してください。低レベルの呼び出しは、強力な不変条件によって安全である可能性があります。一見普通のパラメータ変更でも、オラクルやアップグレードを制御する場合は重大な問題となる可能性があります。修正後、差分を確認し、関連するテストを再実行し、テストスイート全体を再実行して、回帰がないか確認してください。デプロイされたアドレスが既にアップグレードまたは変更されている場合は、実際のオンチェーン実装と構成を再テストしてください。

避けるべきよくある監査ミス

  • 「ソースコードは検証済みなので安全です。」検証はソースコードとバイトコードの対応関係を確立するものであり、設計の妥当性を保証するものではありません。
  • 「スキャナーは何も検出しなかった。つまり、バグはない。」ツールは既知のパターンに対して最も効果を発揮するが、経済的な欠陥や契約間の不備については、多くの場合、人間の分析が必要となる。
  • 「このプロジェクトには監査レポートがあるので、現在の展開状況は網羅されています。」レポートに記載されているコミット、スコープ、展開先アドレス、修正内容、アップグレード履歴を比較してください。
  • 「ファジングテストに合格したので、不変条件は正しい。」まず、不変条件が意図した経済特性を表していること、およびハンドラが意味のある状態に到達することを確認してください。
  • 「管理者による制御はセキュリティ上の問題ではない。」これは意図的な信頼の前提かもしれないが、ユーザーは誰が発行、一時停止、パラメータ変更、またはアップグレードできるかを確認できるべきである。

結果を信頼する前に、最終的な自己チェックを行ってください。

あなたは以下の質問に「はい」と答えられるはずです。

  • チェーン、アドレス、バイトコード、プロキシ、実装、ビルド設定を正確に記録しましたか?
  • 状態変化を引き起こすすべてのエントリーポイントと、それが影響を与える可能性のある資産をすべて洗い出しただろうか?
  • コンパイルは正しく行われたか、警告は確認されたか、自動検出された問題の優先順位付けは適切に行われたか?
  • 外部呼び出し、コールバック、低レベル呼び出し、および障害発生経路をすべて追跡しましたか?
  • 丸め処理、制限値、ゼロ値、古いデータ、および繰り返し操作についてテストしましたか?
  • 特権ロール、キー、遅延、初期化子、およびアップグレードパスをすべてマッピングしましたか?
  • 私は意味のある曖昧さと不変の反例を保持できただろうか?
  • 独立したレビュー担当者は、それぞれの発見事項を再現し、それぞれの修正内容を検証できますか?

いずれかの回答が「いいえ」の場合は、監査を不完全とみなし、不足している証拠を明記してください。「安全」という曖昧な結論よりも、明確な制限事項を示す方がはるかに有用です。スマートコントラクトのセキュリティは継続的なプロセスであり、アップグレード、依存関係の変更、新しい統合、権限の変更など、あらゆる変更によって新たなレビュー範囲が生じる可能性があります。

コメントを残す

仮想通貨におけるコインとトークンの違いとは?

仮想通貨におけるコインとトークンの違いとは?

仮想通貨コインとトークンの違い、ネットワーク所有権、手数料、セキュリティ、管理体制、ユースケース、そしてそれぞれの資産がどのようなニーズに適しているかなどについて学びましょう。

暗号資産ポートフォリオのリスク管理:資産配分の方法

暗号資産ポートフォリオのリスク管理:資産配分の方法

リスク許容度、投資期間、分散投資、保管、流動性、リバランスといった要素に基づいて、万能な公式に頼ることなく、暗号資産をどのように配分するかを学びましょう。

暗号プロジェクトのスマートコントラクトを監査するためのステップバイステップガイド

暗号プロジェクトのスマートコントラクトを監査するためのステップバイステップガイド

暗号資産プロジェクトのスマートコントラクトを監査する方法を、デプロイメントとマッピング権限の検証から、ロジック、アップグレード、修正のテストまで、段階的に学びましょう。

長期的な暗号資産保有ポートフォリオ構築のための究極ガイド

長期的な暗号資産保有ポートフォリオ構築のための究極ガイド

リスクを最優先とする枠組みに基づき、資産配分、資産選択、保管、購入規律、リバランス、記録管理、詐欺回避などを行い、長期的な暗号資産保有ポートフォリオを構築しましょう。

On-Chain Analysis for Beginners: How to Track Whale Wallets and Smart Money

On-Chain Analysis for Beginners: How to Track Whale Wallets and Smart Money

Learn how to read on-chain data, track whale wallets, evaluate smart-money labels, and separate verifiable blockchain facts from inference before acting on wallet activity.

暗号資産先物における「証拠金不足」エラー:その意味と解決方法

暗号資産先物における「証拠金不足」エラー:その意味と解決方法

仮想通貨先物取引プラットフォームで「証拠金不足」エラーが表示される理由、原因の特定方法、安全な修正方法、そして次の取引を行う前に証拠金問題を回避する方法を学びましょう。

バイナンス・ローンチパッドとローンチプール:参加方法と新規トークンの獲得方法

バイナンス・ローンチパッドとローンチプール:参加方法と新規トークンの獲得方法

Binance LaunchpadとLaunchpoolの仕組み、参加資格の確認方法、安全な参加方法、報酬の追跡方法、制限事項とリスクについて学びましょう。

CEXおよびDEXにおける「スリッページ許容範囲超過」エラー:その解決方法

CEXおよびDEXにおける「スリッページ許容範囲超過」エラー:その解決方法

CEX(中央取引所)とDEX(分散取引所)における「スリッページ許容範囲超過」の意味、取引が失敗したかどうかを確認する方法、そしていつ更新、注文サイズの縮小、指値注文の使用、または許容範囲の調整を行うべきかを学びましょう。

Bybitのコピートレーディング:トップクラスの仮想通貨トレーダーをフォローしてコピーする方法

Bybitのコピートレーディング:トップクラスの仮想通貨トレーダーをフォローしてコピーする方法

Bybitのコピー取引の仕組み、マスタートレーダーの評価方法、コピーパラメータの設定方法、リスク管理方法、コピーされたUSDT無期限取引の監視方法について学びましょう。

トークノミクスを理解する:需要と供給がコインの価格に与える影響

トークノミクスを理解する:需要と供給がコインの価格に与える影響

トークンの供給、需要、ロック解除、発行、焼却、およびユーティリティが仮想通貨の価格にどのように影響するか、そしてトークノミクスでは予測できないことについて学びましょう。