👾

ERC165を理解する

2023/02/20に公開

ERC165とは?

  • 「このコントラクトは、これらのメソッドを実装してますよ!」を問い合わせ可能にする規格
  • 「○○規格に準拠してるよね?」を外部から確認するときに使えそう
  • 実装の中身自体を保証するわけではないことに注意
    • transfer(address, address, uint256)というメソッドが存在することは保証するが、どんな実装かは関係ない

OpenZeppelinの実装を覗いてみる

まずは interface から

IERC165.sol
interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
  • メソッドが1つ

次は実装を見てみる

ERC165.sol
abstract contract ERC165 is IERC165 {
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

supportsInterface 関数の引数と type(IERC165).interfaceId を比較することで「このコントラクトは、これらのメソッドを実装してますよ!」を担保しているみたい。type(IERC165).interfaceIdinterface として定義したものに自動付与される変数。

ここで、interfaceId の値がどうやって決まっているのか気になったので、値の導出に関係のある項目とそうじゃない項目を下記にまとめる

# 関係する項目
- 関数名
- 引数の型
- 引数の順序

# 関係しない項目
- public, private, external, internal
- pure, view
- 戻り値 
- 関数の実装順序(test1関数が先に実装されていようがtest2が先だろうが同じ)
- 関数の実装
- イベントの有無

つまり、「関数名、引数の型、引数の順序は保証するけど、それ以外は知らん!」なことがわかる。

実際にどうやって使われてるの?

ERC721だと、こんな感じで使われてます。

  • ERC165の interfaceId との比較とは別に
  • 新たにサポートする interfaceId と比較することを追加する
ERC721.sol
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
    return
        interfaceId == type(IERC721).interfaceId ||
        interfaceId == type(IERC721Metadata).interfaceId ||
        super.supportsInterface(interfaceId);
}

参考

https://zenn.dev/techstart/articles/f513724b0cb387
https://y-nakajo.hatenablog.com/entry/2018/02/04/235505

Discussion