ERC-165这个标准用于发布和检测智能合约实现了哪些接口。
当我们需要和一个合约进行交互时,可能并不清楚他是否实现了某些合约例如”ERC20ERC721″等。所以可以先通过Erc165进行查询(该合约必须实现ERC165),就可以避免很多交互的问题。
ERC165 标准
ERC165 标准,就是一个接口,里面就一个方法——supportsInterface;用户可以通过调用此方法,输入相应查询的接口ID,查询该合约是否实现了对应的接口ID;
interface IERC165 {
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
ERC165接口ID 为 0x01ffc9a7;
接口ID是如何计算出来的呢?
接口是由以太坊ABI定义的一组函数选择器。函数选择器,就是函数签名(如:”myMethod(uint256,string)”)的 Keccak(SHA-3)哈希的前 4 字节。有两种方式生成:
- bytes4(keccak256(‘supportsInterface(bytes4)’));
- supportsInterface(bytes4).selector
接口ID(interface identifier)定义为接口中所有函数选择器的异或(XOR),下例中,通过calculateSelector函数计算Animal的接口ID。
interface Animal {
function run() external pure;
function eat(int) external pure;
}
contract Selector {
function calculateSelector() public pure returns (bytes4) {
Animal a;
return a.run.selector ^ a.eat.selector;
}
}
具体如何如何应用呢?
我们继续使用Animal这个例子,我们分别实现了Dog和Cat两个合约,都实现了Animal和IERC165接口;方式略有不同,
Dog使用supportsInterface的pure(纯函数)实现。 最坏情况下的执行成本是236 gas,但gas随着支持的接口数量增加而线性增加。
Cat这种方法使用supportsInterface的view (视图函数)实现。 任何输入的执行成本都是586 gas。 但合约初始化需要存储每个接口(SSTORE是20,000 gas)。 ERC165MappingImplementation合约是通用的,可重用的。
interface IERC165 {
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
interface Animal {
function run() external;
function eat() external ;
}
contract Dog is IERC165,Animal {
function supportsInterface(bytes4 interfaceID) external view returns (bool){
Return interfaceID == 0x01ffc9a7 || interfaceID == (this.run.selector ^ this.eat.selector)
}
function eat() external {}
function run() external {}
}
//========================================================
contract ERC165MappingImplementation is IERC165 {
mapping(bytes4 => bool) internal supportedInterfaces;
function ERC165MappingImplementation() internal {
supportedInterfaces[this.supportsInterface.selector] = true;
}
function supportsInterface(bytes4 interfaceID) external view returns (bool) {
return supportedInterfaces[interfaceID];
}
}
contract Cat is ERC165MappingImplementation, Animal{
function Cat() public {
supportedInterfaces[this.eat.selector ^ this.run.selector] = true;
}
function eat() external {}
function run() external {}
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
相关推荐: 粘包/拆包问题一直都存在,只是到TCP就拆不动了。
OSI open-system-Interconnection TCP/IP 5层协议栈 应用层和操作系统的边界是 系统调用 ,对应到网络编程是socket api TCP/UDP 概况 TCP粘包问题 TCP/IP报头深思 OSI开放系统互联 定义了网络框架…