抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

1. ERC165简介

​ 简单来说该协议是用来检测智能合约是否实现了某个接口。

2. ERC165的工作原理

​ ERC165中只定义了一个函数,即supportsInterface(),如下:

1
2
3
4
5
6
7
8
9
10
11
pragma solidity ^0.4.20;

interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

​ 简单来说,如果要判断A是否实现了SUPER接口,则A需要实现ERC165中的函数,判断原理则是,调用A中的supportsInterface函数,该函数会判等传入的参数,如果A实现了SUPER的接口,那么函数体的内容应该是:

1
2
3
function supportsInterface(bytes4 interfaceID) external view returns (bool) {
return type(SUPER).interfaceId == interfaceID;
}

这样就可以初步判断该合约实现了某一接口,但是仅仅初步,因为你可以自己编写函数体的返回值,比如我没有实现B接口,我可以自己设置返回值为:

1
2
3
function supportsInterface(bytes4 interfaceID) external view returns (bool) {
return type(B).interfaceId == interfaceID;
}

而合约中并没有实现B接口中函数。比如,别人问你有钱吗,你甩出一张银行卡说里面有一个“小目标”,当然因为你看不见银行卡里面有多少钱,你暂且可以相信你有钱。就好比调用supportsInterface函数来初步判断。具体是否实现这些函数,还得具体调用某些功能来检测才行。

3. ERC165接口的计算原理

- 一个接口的的interfaceID是通过,计算接口中所有函数选择器的异或值,即Dog的interfaceID计算如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface Dog {
function eat() external;
function shout() external;
}

contract Test {

function calDogInterfaceID() external pure returns(bytes4, bytes4) {
bytes4 result = Dog.eat.selector ^ Dog.shout.selector;
return (type(Dog).interfaceId, result);
}
}
  • 当然也会有接口继承的时候,假如Cat接口继承了Animals接口,那么判断是否实现Cat接口该如何计算interfaceId,只需要计算在Cat接口中定义的函数即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface Animals {
function run() external;
function breath() external;
}

interface Dog {
function eat() external;
function shout() external;
}

contract Test {

function calDogInterfaceID() external pure returns(bytes4, bytes4) {
bytes4 result = Dog.eat.selector ^ Dog.shout.selector;
return (type(Dog).interfaceId, result);
}

}

根据运行结果可验证:

image-20240419141733711

评论



政策 · 统计 | 本站使用 Volantis 主题设计