👾
ERC165を理解する
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).interfaceId
は interface
として定義したものに自動付与される変数。
ここで、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);
}
参考
Discussion