スマート・コントラクトの検証
スマート・コントラクトは「トラストレス」であるように設計されています。つまり、ユーザーはコントラクトを操作する前に、サードパーティ(開発者や企業など)を信頼する必要がありません。トラストレス性の要件として、ユーザーや他の開発者はスマート・コントラクトのソースコードを検証できる必要があります。ソース・コード検証により、公開されたコントラクトのコードが、イーサリアムのブロックチェーン上のコントラクトのアドレスで実行されているコードと同じであることが、ユーザーや開発者に保証されます。
「ソース・コード検証」と「形式的検証」を区別することが重要です。後で詳しく説明するソース・コード検証とは、高水準言語(Solidityなど)で記述されたスマート・コントラクトのソースコードが、コントラクトのアドレスで実行されるのと同じバイトコードにコンパイルされることを検証することです。一方、形式的検証は、スマート・コントラクトの正確性、つまりコントラクトが期待通りに動作することを検証することを指します。文脈にもよりますが、コントラクトの検証は通常、ソース・コード検証を意味します。
ソース・コード検証とは何ですか?
スマート・コントラクトをイーサリアム仮想マシン (EVM)にデプロイする前に、開発者はコントラクトのソースコード(Solidityなどの高水準プログラミング言語で書かれた命令)をバイトコードにコンパイルします。EVMは高水準の命令を解釈できないため、EVMでコントラクトのロジックを実行するには、ソースコードをバイトコード(つまり、低水準の機械語命令)にコンパイルする必要があります。
ソース・コード検証とは、スマート・コントラクトのソースコードと、コントラクト作成時に使用されたコンパイル済みのバイトコードを比較し、違いがないかを検出することです。宣伝されているコントラクトのコードが、ブロックチェーン上で実際に実行されているものと異なる可能性があるため、スマート・コントラクトの検証は重要です。
スマート・コントラクトの検証により、機械語を読むことなく、記述された高水準言語を通じてコントラクトが何を行うかを調査できるようになります。関数、値、そして通常は変数名やコメントも、コンパイルおよびデプロイされた元のソースコードと同じままです。これにより、コードを読むのがはるかに簡単になります。また、ソース検証はコードのドキュメント化にも役立つため、エンドユーザーはスマート・コントラクトが何を行うように設計されているかを知ることができます。
完全な検証とは何ですか?
ソースコードの中には、コメントや変数名など、コンパイルされたバイトコードに影響を与えない部分があります。つまり、変数名やコメントが異なる2つのソースコードでも、同じコントラクトを検証できるということです。そのため、悪意のあるアクターがソースコード内に欺瞞的なコメントを追加したり、誤解を招く変数名を付けたりして、元のソースコードとは異なるソースコードでコントラクトを検証させることが可能です。
ソースコードの正確性の_暗号論的保証_として、またコンパイル情報の_フィンガープリント_として機能する追加データをバイトコードに付加することで、これを回避できます。必要な情報はSolidityのコントラクトのメタデータ (opens in a new tab)にあり、このファイルのハッシュがコントラクトのバイトコードに付加されます。実際の動作はメタデータ・プレイグラウンド (opens in a new tab)で確認できます。
メタデータ・ファイルには、ソースファイルやそのハッシュなど、コントラクトのコンパイルに関する情報が含まれています。つまり、コンパイル設定やソースファイルの1バイトでも変更されると、メタデータ・ファイルも変更されます。その結果、バイトコードに付加されるメタデータ・ファイルのハッシュも変更されます。したがって、コントラクトのバイトコードと付加されたメタデータのハッシュが、提供されたソースコードおよびコンパイル設定と一致する場合、元のコンパイルで使用されたソースコードと1バイトも違わず完全に同じであることが確信できます。
メタデータのハッシュを活用するこのタイプの検証は、「完全な検証 (opens in a new tab)」(または「完璧な検証」)と呼ばれます。メタデータのハッシュが一致しない場合、または検証で考慮されない場合は「部分的な一致」となり、現在はこちらがコントラクトを検証する一般的な方法です。完全な検証を行わないと、検証済みのソースコードに反映されない悪意のあるコードを挿入する (opens in a new tab)ことが可能です。ほとんどの開発者は完全な検証について認識しておらず、コンパイル時のメタデータ・ファイルを保持していないため、これまで部分的な検証がコントラクトを検証する事実上の標準的な方法となっていました。
なぜソース・コード検証が重要なのですか?
トラストレス性
トラストレス性は、間違いなくスマート・コントラクトと分散型アプリケーション (dapp)の最大の前提です。スマート・コントラクトは「イミュータブル」であり、変更することはできません。コントラクトは、デプロイ時にコードで定義されたビジネスロジックのみを実行します。つまり、開発者や企業は、イーサリアムにデプロイした後にコントラクトのコードを改ざんすることはできません。
スマート・コントラクトがトラストレスであるためには、コントラクトのコードが独立した検証のために利用可能である必要があります。すべてのスマート・コントラクトのコンパイル済みバイトコードはブロックチェーン上で公開されていますが、低水準言語は開発者にとってもユーザーにとっても理解するのが困難です。
プロジェクトは、コントラクトのソースコードを公開することでトラスト前提を減らします。しかし、これは別の問題を引き起こします。公開されたソースコードがコントラクトのバイトコードと一致することを検証するのは困難です。このシナリオでは、ユーザーはブロックチェーンにデプロイする前に開発者がコントラクトのビジネスロジックを変更しない(つまり、バイトコードを変更しない)ことを信頼しなければならないため、トラストレス性の価値が失われます。
ソース・コード検証ツールは、スマート・コントラクトのソースコード・ファイルがアセンブリコードと一致することを保証します。その結果、ユーザーがサードパーティを盲目的に信頼するのではなく、コントラクトに資金を入金する前にコードを検証するトラストレスなエコシステムが実現します。
ユーザーの安全性
スマート・コントラクトでは、通常、多額の資金がステークされます。そのため、使用する前に、より高いセキュリティ保証とスマート・コントラクトのロジックの検証が求められます。問題は、悪徳な開発者がスマート・コントラクトに悪意のあるコードを挿入してユーザーを欺く可能性があることです。検証を行わないと、悪意のあるスマート・コントラクトにバックドア (opens in a new tab)、物議を醸すアクセス制御メカニズム、悪用可能な脆弱性など、ユーザーの安全を脅かすものが検出されずに残る可能性があります。
スマート・コントラクトのソースコード・ファイルを公開することで、監査人などの関心を持つ人々が、潜在的な攻撃ベクトルについてコントラクトを評価しやすくなります。複数の当事者が独立してスマート・コントラクトを検証することで、ユーザーはそのセキュリティについてより強力な保証を得ることができます。
イーサリアムのスマート・コントラクトのソース・コード検証方法
イーサリアムにスマート・コントラクトをデプロイするには、データ・ペイロード(コンパイル済みバイトコード)を含むトランザクションを特別なアドレスに送信する必要があります。データ・ペイロードは、ソースコードをコンパイルし、トランザクション内のデータ・ペイロードにコントラクト・インスタンスのコンストラクタ引数 (opens in a new tab)を付加することで生成されます。コンパイルは決定論的です。つまり、同じソースファイルとコンパイル設定(コンパイラのバージョン、オプティマイザなど)を使用すれば、常に同じ出力(つまり、コントラクトのバイトコード)が生成されます。
スマート・コントラクトの検証には、基本的に以下の手順が含まれます。
-
ソースファイルとコンパイル設定をコンパイラに入力します。
-
コンパイラがコントラクトのバイトコードを出力します。
-
指定されたアドレスにデプロイされたコントラクトのバイトコードを取得します。
-
デプロイされたバイトコードと再コンパイルされたバイトコードを比較します。コードが一致する場合、コントラクトは提供されたソースコードとコンパイル設定で検証されます。
-
さらに、バイトコードの末尾にあるメタデータのハッシュが一致する場合、完全な一致となります。
これは検証の単純化された説明であり、イミュータブルな変数 (opens in a new tab)を持つ場合など、これでは機能しない多くの例外があることに注意してください。
ソース・コード検証ツール
コントラクトを検証する従来の手順は複雑になる可能性があります。そのため、イーサリアムにデプロイされたスマート・コントラクトのソース・コード検証ツールが存在します。これらのツールは、ソース・コード検証の大部分を自動化し、ユーザーの利益のために検証済みのコントラクトをキュレーションします。
Etherscan
Etherscanは主にイーサリアムのブロック・エクスプローラーとして知られていますが、スマート・コントラクトの開発者やユーザー向けにソース・コード検証サービス (opens in a new tab)も提供しています。
Etherscanを使用すると、元のデータ・ペイロード(ソースコード、ライブラリのアドレス、コンパイラ設定、コントラクトのアドレスなど)からコントラクトのバイトコードを再コンパイルできます。再コンパイルされたバイトコードがオンチェーンのコントラクトのバイトコード(およびコンストラクタ・パラメータ)と関連付けられている場合、コントラクトは検証されます (opens in a new tab)。
検証されると、コントラクトのソースコードには「Verified(検証済み)」ラベルが付与され、他の人が監査できるようにEtherscanで公開されます。また、検証済みのソースコードを持つスマート・コントラクトのリポジトリであるVerified Contracts (opens in a new tab)セクションにも追加されます。
Etherscanは、コントラクトの検証に最も使用されているツールです。しかし、Etherscanのコントラクト検証には欠点があります。オンチェーンのバイトコードと再コンパイルされたバイトコードのメタデータのハッシュを比較できないのです。したがって、Etherscanでの一致は部分的な一致となります。
Etherscanでのコントラクト検証の詳細 (opens in a new tab)
Blockscout
Blockscout (opens in a new tab)はオープンソースのブロック・エクスプローラーであり、スマート・コントラクトの開発者やユーザー向けにコントラクト検証サービス (opens in a new tab)も提供しています。オープンソースの代替手段として、Blockscoutは検証の実行方法に透明性を提供し、検証プロセスを改善するためのコミュニティの貢献を可能にします。
他の検証サービスと同様に、Blockscoutではバイトコードを再コンパイルし、デプロイされたコントラクトと比較することで、コントラクトのソースコードを検証できます。検証されると、コントラクトは検証ステータスを受け取り、ソースコードは監査や操作のために一般公開されます。検証済みのコントラクトは、簡単に閲覧やディスカバリーができるように、Blockscoutの検証済みコントラクト・リポジトリ (opens in a new tab)にもリストされます。
Sourcify
Sourcify (opens in a new tab)は、オープンソースで分散型のコントラクト検証ツールです。ブロック・エクスプローラーではなく、さまざまなEVMベースのネットワーク (opens in a new tab)上のコントラクトのみを検証します。他のツールがその上に構築するためのパブリック・インフラストラクチャとして機能し、メタデータ・ファイルにあるABIやNatSpec (opens in a new tab)コメントを使用して、より人間に優しいコントラクトの操作を可能にすることを目指しています。
Etherscanとは異なり、Sourcifyはメタデータのハッシュによる完全な一致をサポートしています。検証済みのコントラクトは、HTTPおよび分散型のコンテンツ・アドレス (opens in a new tab)・ストレージであるIPFS (opens in a new tab)上のパブリック・リポジトリ (opens in a new tab)で提供されます。付加されたメタデータのハッシュはIPFSハッシュであるため、IPFS経由でコントラクトのメタデータ・ファイルを取得できます。
さらに、これらのファイルのIPFSハッシュもメタデータに含まれているため、IPFS経由でソースコード・ファイルを取得することもできます。APIやUI (opens in a new tab)経由でメタデータ・ファイルとソースファイルを提供するか、プラグインを使用することで、コントラクトを検証できます。また、Sourcifyの監視ツールは新しいブロックでのコントラクト作成をリッスンし、メタデータとソースファイルがIPFSで公開されている場合はコントラクトの検証を試みます。
Sourcifyでのコントラクト検証の詳細 (opens in a new tab)
Tenderly
Tenderlyプラットフォーム (opens in a new tab)を使用すると、Web3開発者はスマート・コントラクトの構築、テスト、監視、運用を行うことができます。デバッグツールと可観測性、およびインフラストラクチャの構成要素を組み合わせることで、Tenderlyは開発者がスマート・コントラクトの開発を加速するのを支援します。Tenderlyの機能を完全に有効にするには、開発者はいくつかの方法を使用してソース・コード検証を実行する (opens in a new tab)必要があります。
コントラクトはプライベートまたはパブリックに検証することが可能です。プライベートに検証された場合、スマート・コントラクトはあなた(およびプロジェクトの他のメンバー)にのみ表示されます。コントラクトをパブリックに検証すると、Tenderlyプラットフォームを使用するすべてのユーザーに表示されるようになります。
ダッシュボード (opens in a new tab)、Tenderly Hardhatプラグイン (opens in a new tab)、またはCLI (opens in a new tab)を使用してコントラクトを検証できます。
ダッシュボードからコントラクトを検証する場合、ソースファイルまたはSolidityコンパイラによって生成されたメタデータ・ファイル、アドレス/ネットワーク、およびコンパイラ設定をインポートする必要があります。
Tenderly Hardhatプラグインを使用すると、より少ない労力で検証プロセスをより詳細に制御でき、自動(ノーコード)検証と手動(コードベース)検証のいずれかを選択できます。
