本文へスキップ
ethexplorer.org

技術ガイド · 検証済みソース · プロキシ

スマートコントラクト・エクスプローラーで、資産を預けるコードを読む

検証済みソースコード、Read/Writeタブ、ABI、プロキシ、イベント、管理者キーを、専門用語に頼らず解説します。最後に、どんなアドレスにも使える5ステップのチェック手順を紹介します。

2013年創業の規制対応取引所

  • Etherscan · Sourcify · Blockscout
  • EIP-1967プロキシ
  • Tenderly・Phalconのトレース

著者 ethexplorer.org 編集部 更新日 12 分で読めます

イーサリアム上のトークンも、NFTコレクションも、レンディング市場もブリッジも、その正体はすべてスマートコントラクトです。あるアドレスに保存されたバイトコードが、すべてのノードで書かれたとおりに実行されています。イーサリアムのスマートコントラクト・エクスプローラーは、ブロックエクスプローラーの中でも、そのバイトコードを人間が調べられる形に戻してくれる部分です。作者が公開していればソースコードを表示し、コードを1行も書かずに関数を呼び出させてくれ、コントラクトが発行したイベントを一覧にし、誰がデプロイしたのかを教えてくれます。

使いこなすのに、Solidityの開発者である必要はありません。「検証済み」が本当は何を意味するのか、プロキシをどう見分けるのか、管理者キーがどこにあるのか。この3点を知っているだけで、かなりの種類のリスクを避けられます。このガイドでは、コントラクトページをタブごとに順番に見ていき、最後に5ステップの確認手順をまとめます。保有者の集中度やハニーポットといったトークン特有のチェックについては、姉妹編のトークン・エクスプローラーのガイドをご覧ください。

Etherscan・Sourcify・Blockscoutでいう「検証済みソースコード」とは

コントラクトアドレスに保存されているのは、バイトコードだけです。「このSolidityファイルからこのバイトコードができた」と主張するのは誰にでもできます。その主張をエクスプローラーが確かめる仕組みが「検証(verification)」です。作者はソースファイル、コンパイラーのバージョン、オプティマイザーの設定、コンストラクター引数を提出します。エクスプローラーはそれをコンパイルし、結果をチェーン上のバイトコードと突き合わせます。一致すれば、緑のチェックマークとともにソースコードがコントラクトの横に公開されます。

Etherscanは、作者のコードとコンストラクター引数でデプロイ済みコントラクトを再現できたExact Matchと、Similar Matchを区別しています。後者は、新しいコントラクトのバイトコードがすでに検証済みのものと一致したときにEtherscanが自動で付けるものです。ファクトリーから大量にデプロイされるクローンには便利ですが、コンストラクター引数は考慮されません。そしてコンストラクター引数次第で、コントラクトの振る舞いは変わり得ます。大きな金額がかかっているときは、Exact Matchのほうを信頼してください。

Sourcifyは、もともとイーサリアム財団のもとで育ったオープンソースの検証サービスで、Solidityコンパイラーがバイトコードの末尾にハッシュとして埋め込むメタデータファイルを利用します。現在は結果をexact matchとmatchの2種類で呼んでいますが、多くのツールでは今も旧名の「full」「partial」が表示されます。exact matchは、コメントやファイルパスを含めてすべてがバイト単位で同一であることを意味します。matchは、実行コードは同一でもメタデータが異なる状態です。どちらもロジックを証明しており、名称が変わったのは「partial(部分的)」という言葉のせいで未検証だと誤解する人が多かったからです。

Blockscoutは独自の検証方法(フラット化したソース、Standard JSON Input、Hardhat・Foundryのプラグイン)に対応し、さらにSourcifyとも連携しているため、Sourcifyで検証されたコントラクトはBlockscout上でも検証済みとして表示されることがあります。詳しくはBlockscoutのレビューで解説しています。

Read ContractとWrite Contractタブの読み方

コントラクトが検証されると、エクスプローラーはそのABIを把握し、2つの入力フォームを自動で用意します。Read Contractには、viewpureの関数がすべて並びます。呼び出しは無料で、ウォレットも不要、返ってくるのはチェーン上の現在の値です。トークンのtotalSupply()、ボールトのowner()、プロトコルがpaused()になっているかどうか。誰かが作ったダッシュボードを信用せずに、コントラクトに関する事実を確かめるいちばん速い方法です。

Write Contractには、状態を変更する関数が並びます。エクスプローラーはウォレットの接続を求め、入力したパラメーターを本物のトランザクションに組み立てて、署名のためにウォレットへ渡します。プロジェクトのWebサイトが落ちていて資金を引き出したいとき、あるいは第三者のサイトを使わずに承認(approve)を取り消したいときには、本当に役立ちます。一方で、ミスが起きやすい場所でもあります。金額はトークンの最小単位で入力するため、1 USDCは1000000、1 WETHは1000000000000000000です。開発者でない方にとってWriteタブは、クリックするより「読む」ために使うほうが有益です。状態を変える関数の一覧を見れば、オーナーや利用者に何ができるのかがわかります。

ABIと関数セレクターをやさしく解説

ABI(アプリケーション・バイナリー・インターフェース)は、コントラクトの関数とイベントを記述したJSONです。関数名、引数の型、戻り値の型が書かれており、エクスプローラーはこれを使ってトランザクションをデコードします。コントラクトにトランザクションを送るとき、入力データ(input data)の先頭には4バイトの関数セレクターが入ります。これは関数シグネチャのkeccak-256ハッシュの先頭4バイトです。セレクターの後ろはすべて引数で、それぞれ32バイトに詰め物(パディング)されています。

// ERC-20の3つの関数と、それぞれの4バイトのセレクター
function transfer(address to, uint256 amount) external returns (bool);   // 0xa9059cbb
function approve(address spender, uint256 amount) external returns (bool); // 0x095ea7b3
function balanceOf(address account) external view returns (uint256);     // 0x70a08231

// セレクター = keccak256("transfer(address,uint256)") の先頭4バイト
// transferのcalldata:
// 0xa9059cbb
//   000000000000000000000000<送付先アドレス、20バイト>
//   <金額を32バイトの符号なし整数で表したもの>

だからこそ、エクスプローラーは未検証コントラクトへのトランザクションでもtransferと表示できるのです。コントラクトのABIがなくても、公開されている署名データベースから0xa9059cbbを認識できるからです。これはフィッシングの手口の説明にもなります。セレクターはたった4バイトなので、攻撃者は意味のない名前を持ちながら、よく知られたセレクターと衝突する関数を作ることができますし、悪意のある関数にclaimRewardsと名付けることもできます。デコードされた関数名はあくまでヒントであり、真実は検証済みのソースコードにあります。実際のトランザクションで入力データをデコードする手順は、トランザクション・エクスプローラーのガイドで紹介しています。

プロキシ:EIP-1967、UUPS、そして実装アドレス

コントラクトはデプロイ後に書き換えられません。そのため、アップグレード可能なシステムは2つに分かれています。状態を保持し、利用者がやり取りするアドレスとなる小さなプロキシと、コードを保持する実装(ロジック)コントラクトです。プロキシはすべての呼び出しをdelegatecallで実装側に転送し、アップグレードとはプロキシの向き先を新しい実装に切り替えることを指します。わかりやすい実例がUSDCです。0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48はプロキシで、トークンのロジックはCircleが差し替え可能な別の実装コントラクトに置かれています。

EIP-1967は、プロキシがその向き先をどこに保存するかを標準化しました。実装アドレスはストレージスロット0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcに、管理者は0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103に置かれます。スロットが固定されているので、エクスプローラーはプロキシを検出し、実装側のABIを使う「Read as Proxy」「Write as Proxy」タブを表示できます。

トランスペアレント・プロキシでは、アップグレード関数はプロキシ側にあり、管理者だけが呼び出せます。UUPSプロキシ(ERC-1822由来)では、アップグレード関数が実装コントラクト自身に置かれます。プロキシを軽く保てる反面、実装にバグがあるとアップグレード自体ができなくなる恐れがあります。ビーコン・プロキシは、多数のプロキシを1つの「ビーコン」に向け、そのビーコンが実装を指定する方式です。

安全確認という観点でのポイントは単純です。プロキシを読んでいるとき、あなたは実際に動くコードを読んでいません。実装アドレスをクリックして、それが検証済みであることを確かめ、次にアップグレードを呼び出せるのが誰かを突き止めてください。そのキーを握る者が、コントラクト内のすべてのトークンを握っています。

イベント、ログ、バイトコード

コントラクトは、何が起きたかを記録するためにイベントを発行します。TransferApprovalOwnershipTransferredUpgradedPausedなどです。各イベントはトランザクションのレシートにログとして残り、最大4つのインデックス付きトピックと1つのデータ欄を持ちます。コントラクトページのEventsタブはこうしたログの時系列フィードで、セキュリティの観点からはまさに宝の山です。2日前のUpgradedイベント、見知らぬアドレスへの新たなRoleGranted、作られたばかりのウォレットへのOwnershipTransferred。事故の前触れになるのは、まさにこうした変化です。

バイトコードタブには、デプロイされた生のコードが表示されます。未検証のコントラクトでは、手がかりはこれしかありません。ツールを使えば大まかな疑似コードに逆コンパイルでき、Otterscanなどのセルフホスト型エクスプローラーを使えば自分のノード上でトレースすることもできます。2025年5月のPectraアップグレード以降は、もう1つ見分けるべきケースが加わりました。普通のウォレットアドレスに、0xef0100の後ろにアドレスが続く短いコードが入っていたら、それはEIP-7702の委任(デリゲーション)です。つまり、そのアカウントは現在、別のコントラクトのコードを実行しています。最近のエクスプローラーはこれにラベルを付けてくれますが、ほかのコントラクトと同じくらい慎重に調べる価値があります。

コントラクトの作成者と作成トランザクション

どのコントラクトページにも、誰がどのトランザクションで作成したのかが表示されています。この1行だけで、驚くほど多くの疑問に答えが出ます。チームの既知のデプロイ用アドレスから作られたのか、それとも1時間前に取引所から資金を受け取ったばかりのアドレスから作られたのか。直接デプロイされたのか、UniswapのプールやSafeウォレットのようにファクトリーコントラクト経由で作られたのか。どんなコンストラクター引数が渡されたのか。作成者をクリックすれば、そのアドレスがほかに何をデプロイしたのかも見えます。放置されたトークンがずらりと並んでいるなら、それは偶然ではなくパターンです。ウォレットの素性を手早く調べる方法は、アドレス・エクスプローラーのガイドで解説しています。

5ステップでコントラクトを確認する

トークンを承認(approve)したり資金を預けたりする前に、どのコントラクトにもこの手順を当てはめてください。EtherscanやBlockscoutなら、5分ほどで終わります。

  1. 1 STEP 01

    アドレスとデプロイ者を確認する

    アドレスはプロジェクトの公式ドキュメントから入手し、エクスプローラーで開きます。コントラクトの作成者(デプロイ者)と作成トランザクションを見て、「誰が・いつ・どのファクトリーから」デプロイしたのかを確かめてください。

  2. 2 STEP 02

    検証ステータスを確認する

    Etherscan、Sourcify、Blockscoutのいずれかで、Exact Match(完全一致)やMatchになっているかを探します。検証済みソースがないということは、読めないバイトコードを信用するということです。

  3. 3 STEP 03

    プロキシの実装先をたどる

    エクスプローラーがプロキシと表示している場合は、実装(implementation)アドレスを開き、そちらのコードを読みます。誰がアップグレードできるのかもメモしておきましょう。

  4. 4 STEP 04

    管理者権限を洗い出す

    Read Contractでowner()、各種ロール、プロキシ管理者を確認します。それは単一のウォレットか、マルチシグか、それとも遅延期間つきのタイムロックか、を見極めてください。

  5. 5 STEP 05

    イベントを読み、シミュレーションする

    直近のイベントからアップグレード、ロール変更、一時停止(pause)を拾い、署名する前にTenderlyなどのツールで自分のトランザクションをシミュレーションします。

セキュリティチェック:管理者キー、タイムロック、監査

DeFiの大きな損失の多くは、難解な数学のバグではなく「鍵」が原因です。ですから、プロキシの実装先を突き止めたら、次は誰が権限を持っているのかを見てください。owner()を呼び出し、DEFAULT_ADMIN_ROLEMINTER_ROLEPAUSER_ROLEなどのロールを確認し、プロキシ管理者を探します。そして、それぞれのアドレスを開いてみましょう。外部所有アカウント(EOA)であれば、秘密鍵1つでシステム全体を変更できるということです。Safeのマルチシグならそれよりましで、そのページには「7人中4人」のような署名しきい値が表示されます。さらに望ましいのはタイムロックコントラクトです。変更はいったんキューに入れられ、多くの場合24〜48時間以上の公開された待機期間を経てから実行されるため、利用者には資金を引き揚げる時間が生まれます。キューに入った操作は、タイムロック自身のページでイベントとして確認できます。

その次の層が監査です。監査レポートには、レビューした正確なコミットやコントラクトアドレスが記載されているはずです。それを実際にデプロイされているものと照らし合わせてください。監査後に変更されたコードは、監査されていないコードと同じだからです。レポートがプロジェクトのサイトだけでなく、監査会社自身のサイトにも掲載されているかも確認しましょう。バグバウンティ(報奨金制度)の有無や、過去のインシデントへの対応履歴も判断材料になります。とはいえ、これらのどれもコントラクトのリスクをゼロにはしません。だからこそ、ポジションの大きさは常に「失っても耐えられる額」に合わせるべきなのです。

さらに深く:Tenderly、Phalcon、トレース・エクスプローラー

標準的なエクスプローラーが表示するのは、最上位の呼び出しとイベントです。フラッシュローン、複数のプールを経由するスワップ、エクスプロイト(攻撃)のような複雑なトランザクションは、トレースでしか見えない内部呼び出しの中で起きています。Tenderlyは、あらゆるトランザクションを完全なコールツリー、状態変化、1行ずつ追えるデバッガーつきで再生でき、まだ送信していないトランザクションのシミュレーションもできます。大きな署名の前にシミュレーションすることは、身につけるべき最高の習慣です。BlockSecのPhalcon Explorerは、呼び出しの流れ、資金の流れ、残高の変化に焦点を当てており、セキュリティ研究者が攻撃を再構成する際によく使っています。どちらもEtherscanの代替ツールまとめでほかの選択肢と比較しています。

それでも、日々のチェックの主な舞台はEtherscanかBlockscoutになるでしょう。Etherscanは検証済みコントラクトとラベルの蓄積が最大で、コントラクト関連の機能はEtherscanのレビューで詳しく取り上げています。Blockscoutはソースコード公開型(source-available、以前はGPL-3.0)で、現在はキーなしで使えるAPIを提供しているため、チェックを自動化したいときに重宝します。その方法はエクスプローラーAPIのガイドで説明しています。そして、あるアドレスがコントラクトなのか、検証済みなのか、プロキシなのかをまずざっと確認したいなら、当サイトの無料のイーサリアム・エクスプローラーが数秒で答えを出してくれます。

コントラクトページを読みやすくする習慣

チェックはいつも、名前ではなくアドレスから始めましょう。プロキシではなく、プロキシの実装先を読みましょう。Similar Matchや未検証の状態は、立ち止まる理由だと考えてください。コードを読む前に、まずここ数週間分のEventsタブに目を通しましょう。思わぬ変化が潜んでいるのは、たいてい最近の変更の中だからです。そして、複雑なトランザクションや高額なトランザクションは、先にシミュレーションしてください。こうした習慣が身につけば、スマートコントラクト・エクスプローラーは16進数の壁ではなく、どんなプロトコルにとっても最も正直なドキュメントに変わります。

よくある質問

01

イーサリアムのスマートコントラクト・エクスプローラーとは何ですか?

ブロックエクスプローラーのうち、コントラクトを表示する部分のことです。任意のコントラクトアドレスについて、ソースコード、ABI、Read/Writeタブ、イベント、バイトコード、作成者、作成トランザクションを確認できます。EtherscanとBlockscoutの両方に備わっており、当サイトのライブ・エクスプローラーでも、コントラクトが検証済みかどうか、プロキシかどうかがわかります。
02

Etherscanの「検証済みコントラクト(Verified)」とはどういう意味ですか?

作者が提出したソースコードを、エクスプローラーが同じコンパイラーのバージョンと設定でコンパイルし、そのアドレスにデプロイされているバイトコードと一致した、という意味です。つまり「読んでいるコードが実際に動いているコードである」ことの証明です。コードが安全であることや、作者が誠実であることまでは証明しません。
03

Sourcifyの「exact match」と「match」の違いは何ですか?

exact match(以前の呼び名は「full」や「perfect」)は、メタデータハッシュまで含めて再コンパイル結果のバイトコードが完全に同一であることを示し、コメントやファイル名まで一致しています。match(以前は「partial」)は、実行されるコードは同一ですが、コメントや変数名などメタデータが異なる状態です。どちらもロジックが同じであることを証明しています。
04

プロキシコントラクトの実装先(implementation)はどうやって探せますか?

エクスプローラーは標準的なプロキシを自動検出し、「Read as Proxy」「Write as Proxy」タブとともに実装アドレスを表示します。EIP-1967のプロキシでは、アドレスはストレージスロット0x3608…2bbcに格納されており、アップグレードのたびにログにUpgraded(address)イベントが記録されます。
05

Write Contractタブを使っても安全ですか?

安全性は、あなたが署名するトランザクション次第です。このタブはウォレットを接続し、コントラクトへ本物のトランザクションを送信するため、パラメーターを1つ間違えれば資金を失うこともあります。信頼できるコントラクトに限って使い、単位(多くのトークンは小数点以下18桁)を再確認し、金額が大きいときは先にシミュレーションしてください。

あわせて読みたい