スマート コントラクトのテストは非常に重要です。なぜ?スマート コントラクトは一般的に、本番環境、公開環境、ハッカーのターゲットでは不変であり、多くの場合、重大な経済的影響を伴います。短編?スマート コントラクトを使用すると、失敗したくありません。たくさんテストし、頻繁にテストし、徹底的にテストする必要があります。スマート コントラクト テストには、ユニット テスト、統合テスト、自動テストなど、通常の疑わしいものすべてが含まれますが、ファジングも強くお勧めします。これは、何が起こるかを確認するためだけにランダムな入力を大量にコードにぶつける方法です。
テスト方法としてのファジングとは何か、そして ConsenSys Diligence Fuzzingなどのツールを使用してソフトウェア テスト ワークフローにファジングを簡単に組み込む方法を見てみましょう。サンプルの defi スマート コンタクトを使用してチュートリアルを進め、その方法を確認します。
ファジング テスト(またはファジング テスト) には、予期しない動作を引き起こし、脆弱性を検出するために、スマート コントラクトに対して何百万もの無効で予期しない (半) ランダムなデータを送信することが含まれます。これは、思いもよらないエッジ ケースやシナリオをテストするための、高速で効率的な力ずくの方法です。他のテスト フローと監査を補完します。
ファジングは、従来のフルスタック開発でしばらく使用されていましたが、web3 のスマート コントラクト テストにファジングを適用できる新しいクラスのツールが登場しました。ファジング ツールには、オープン ソースのEchidnaやMythX などがあります。
ただし、この記事では、サービスとしてファジングを提供するDiligence Fuzzingについて詳しく説明します。これは、非常にクールで簡単なファジング方法です。
Diligence Fuzzing を使用するには、 Scribbleを使用してスマート コントラクトに注釈を付けます。基本的に、コード内で Scribble アノテーションを使用して、その関数に期待される出力のタイプをファザーに伝えます。
次のようになります。
/// #invariant {:msg "balances are in sync"} unchecked_sum(_balances) == _totalSupply;
スマート コントラクト コードを送信する Web UI からファザーを呼び出します。実行すると、約 10 分後に、見つかった問題、問題の場所、カバレッジ % などを含むレポートが表示されます。
これは、いくつかのエッジ ケースをチェックするための簡単で強力な方法です。
立ち上げたい新しい DeFi プロトコルと対応するトークンがあるとします。 DeFi は最先端の金融であり、書くのが楽しく、バグがないことが重要です。 DeFi スマート コントラクトには、多くの場合、数百万 (またはそれ以上) のユーザー資金が含まれます。そのため、スマート コントラクトが可能な限り徹底的にテスト (および監査) されていることを確認したいと考えています。
重要な注意: このコードには、意図的に脆弱性が含まれています。これは、ファジングがこれらの間違いをどのように検出できるかを示すためです。このコードを実際に使用しないでください。
始めましょう。
まず、Diligence アカウントが必要です。ディリジェンスにサインアップしてください。 10 時間のファジングを無料で試すことができます。
右上のアカウント名をクリックし、「新しい API キーを作成」をクリックして、名前を付けます。この API キーにより、FaaS に接続できます。
次のリポジトリをクローンします。
https://github.com/ConsenSys/scribble-exercise-1.git
コマンド ラインから、プロジェクトのルート フォルダーとなるリポジトリ フォルダーに移動します。マシンで必要な場合は、Python venv をアクティブにします。次に、次のコマンドを実行して、プロジェクトの依存関係をインストールします。
$ npm i -g eth-scribble ganache truffle $ pip3 install diligence-fuzzing
キーの値に Diligence アカウントの API キーを使用するように.fuzz.yml
ファイルを編集します。
結果のファイルは次のようになります。
.fuzz.yml fuzz: # Tell the CLI where to find the compiled contracts and compilation artifacts build_directory: build/contracts ... campaign_name_prefix: "ERC20 campaign" # Point to your ganache node which holds the seed rpc_url: "http://localhost:8545" key: "DILIGENCE API KEY GOES HERE" ...
では、 contracts/vulnerableERC20.sol
でスマート コントラクトを確認してみましょう。ここに、新しい DeFi プロトコル用の脆弱なトークン (名前の通り!) があります。可能な限りテストする必要があることは明らかです。それでは、ファザーがうまくキャッチできるように、Scribble を使用してチェックを追加しましょう。
コントラクト定義の上に、次を追加します。
/// #invariant "balances are in sync" unchecked_sum(_balances) == _totalSupply;
伝達関数の上に、以下を追加します。
/// #if_succeeds msg.sender != _to ==> _balances[_to] == old(_balances[_to]) + _value; /// #if_succeeds msg.sender != _to ==> _balances[msg.sender] == old(_balances[msg.sender]) - _value; /// #if_succeeds msg.sender == _to ==> _balances[msg.sender] == old(_balances[_to]); /// #if_succeeds old(_balances[msg.sender]) >= _value;
それでは、ファジング テスターが何かをキャッチするかどうか見てみましょう。コントラクトに追加した注釈に注目して、テスト担当者が予想されることを理解できるようにします。また、構成で、テスターは最大 10 分間実行するように設定されているため、すべてをキャッチできない可能性があることに注意してください。
これで、テストの準備が整いました。プロジェクトのルート フォルダーからmake fuzz
を実行して make ファイルを呼び出します。これにより、すべてがコンパイル、ビルドされ、FaaS に送信されます。
ダッシュボードに戻ると、以下のようなものが表示されます。キャンペーンが開始されるまで数秒待ちます。
生成が完了すると、次のようなものが表示されます。
コード カバレッジも表示されます。
数分後、失敗が表示されます。
プロパティをクリックすると、違反が表示されます。はい、バグがあります!行の場所をクリックすると、潜在的なコードの脆弱性の詳細が表示されます。
ここで終わりますが、ファザーを実行し続けると、さらに多くの情報が見つかる可能性があります。
ファジングは、ソフトウェアの開発およびテスト プロセスにおいて重要なステップとなる可能性があります。他の方法では見過ごされる可能性のある潜在的な脆弱性を特定するのに役立ちます。それを使用することで、一般的な落とし穴や課題を認識し、理解し始めます。 Diligence Fuzzingなどのツールを利用して、より優れたスマート コントラクトを作成し、より優れた開発者になりましょう!