スキップしてメイン コンテンツに移動

ERC-165: Standard Interface Detection まとめ

先日EthereumのERC-165を読んでいたので, 備忘録として日本語でまとめを記しておきます.


ERC-165: Standard Interface Detection

このERCでは, スマートコントラクトがどのようなInterfaceを実装しているのかを公開・検出する方法を定義しています.
これによって, 目の前のスマコンがERC-20準拠なのかとか, あのInterfaceを実装しているのかとかを調べることができるという嬉しいポイントがあります.

Interfaceとは?

これこれ. プログラミング言語によってはInterfaceの概念がないものもあったりして馴染みのない方ももしかしたらいるかもしれません.
このコントラクトは, こういうメソッドを持つよ! というお約束を書くアレです.

標準化した内容

以下の4つを標準化しました.
  1. Interfaceの識別方法
  2. コントラクトが実装しているInterfaceを公開する方法
  3. コントラクトがERC-165を実装しているかを検出する方法
  4. コントラクトが, 任意のInterfaceを実装しているかを検出する方法

1. Interfaceの識別方法

Interface識別子というものを導入します.

Interface識別子というのは, 全てのFunction Selectorのxorを取ることで計算されます.
Function Selector自体はbytes4(keccak256("関数名(引数の型)"))で計算されます.

Function Selectorってなんやねんという方は, こちらの記事を読むとスッキリすると思います.

なのでざっくり言うと, 目の前のコントラクトがERC-20に準拠しているか知りたかったら, ERC-20が備えているべきInterfaceの識別子を計算し, それをコントラクトに渡してお前はこのInterface持っとるかと聞けばいいわけですね.

2. コントラクトが実装しているInterfaceを公開する方法

目の前のコントラクトに, 「(少なくとも)このInterfaceをサポートしてますか?」と聞いたら, はい or いいえのbool値を返してほしいですね.
それを標準化しました.
ERC165準拠のコントラクトは, 上記のsupportsInterfaceメソッドを備える必要があります.

このsupportsInterfaceメソッドは, 以下の挙動をします.
  • interfaceIDが, 0x01ffc9a7 → trueを返す
    0x01ffc9a7は, ERC165自体のInterface識別子です.
    bytes4(keccak256("supportsInterface(bytes4)")) == 0x01ffc9a7なので.
  • interfaceIDが, 0xffffffff → falseを返す
  • interfaceIDが, 実装しているInterfaceの識別子 → trueを返す
  • interfaceIDが, 実装していないInterfaceの識別子 → falseを返す

3. コントラクトがERC-165を実装しているかを検出する方法

そもそも, 目の前のコントラクトがsupportsInterfaceメソッドを持っているか知らないと, 問い合わせようもないですよね.
ということで, その確認方法も標準化しました. 以下の順序で行います.
  1. 相手のコントラクトの, supportsInterface関数を呼び出してみるチャレンジ
    contract.supportsInterface(0x01ffc9a7)をやる.
    ここで呼び出しが失敗したり, falseが返ってきたりしたらERC-165を実装していないとわかる
  2. もし1でtrueが返ってきたら, contract.supportsInterface(0xffffffff)を呼び出す
    1でtrueが返ってきたからといって, 安心するべからず. もしかしたらそのsupportsInterface関数は, たまたま同じ名前・引数なだけで, たまたまtrueを返したのかもしれない...中身は, なにか別の目的のためにオレオレ実装されているものかもしれない... ということで, 0xffffffffでも呼び出してみるというわけ.
    ここで呼び出しに失敗したり, falseが返ってこなかったらERC-165を実装していないとわかる.
  3. ここまできたら, ERC-165を実装しているということになる.

4. コントラクトが, 任意のInterfaceを実装しているか検出する方法

ERC-165を実装していることをさきほどの手順で確認した上で, supportsInterfaceメソッドの引数に調べたいInterface識別子を突っ込み, その戻り値で判断します.

おわりに

ERC-165完全理解太郎になった!

参考文献

コメント

このブログの人気の投稿

【論文輪読】CoopEdge: A Decentralized Blockchain-based Platform for Cooperative Edge Computing

研究会の輪読で, 協調エッジコンピューティングについての論文CoopEdgeを読んでまとめたので, スライドを供養しておきます. CoopEdge: A Decentralized Blockchain-based Platform for Cooperative Edge Computingを読む from Hiroki Takemura

Ethereum 署名の流れ

Ethereumでトランザクションに署名をしたり, その検証をしたり, 署名から公開鍵(EOAアドレス)を導出する方法を整理しておきます. 署名でできること 以下ができます. 秘密鍵の所有者が, トランザクションの実行を許可したことを署名によって確認する 1自体(トランザクションの実行を許可したこと)を否定できないことを保証する 秘密鍵の所有者でないと, 有効な署名は作れないので, 当然ですね. 署名されて以来, トランザクションが改ざんされていないことを証明する トランザクションの内容が書き換わると, トランザクションのハッシュ値も変わるので, 署名が無効になります. 署名から, トランザクションを作成したアカウントの特定(EOAアドレス=公開鍵を導出する) トランザクションにはfromアドレスが記載されていないので, 署名から送信元アドレスを計算する必要があります. 署名のデータ 署名には, $(r, s, v)$という3つのデータが入っています. このうち, $v$は チェーン識別子 です. 署名の作成 $m$がトランザクション(nonce, gasPrice, gasLimit, to, value, data, vを適切に設定し, rとsにはゼロを入れたもの)を, RLPでエンコードしたものとします. $k$は, 秘密鍵とします. 署名は, $(r, s) = F_{sig}(m, k) $ という感じで生成します. 署名をやってくれる$F_{sig}$の中身はどうなっとるんじゃいという話ですが, Ethereumで採用されている署名アルゴリズムはECDSA(楕円曲線デジタル署名アルゴリズム)です. 一応その手順を以下に記しておきます. 楕円曲線暗号よくわかっとらんので, 間違ってたりとかしたら教えてください. 一時的な秘密鍵として, 乱数$q$を生成する. $q$に対応する一時的な公開鍵$Q$を, 秘密鍵$q$から生成する. 署名作成のときに一時的に使う公開鍵を, 楕円曲線生成元$G$から生成します. $r$は, 一時公開鍵$Q$のx座標になる まあ楕円曲線ってこんな感じのやつで, 一時公開鍵$Q$は楕円曲線上の点だったと思いますので, そのx座標を$r$とするわけですね. $s = q^{-1}(keccak256(m) + r \cdot k) (\