solidity dapp ERC-165

ERC-165这个标准用于发布和检测智能合约实现了哪些接口。

当我们需要和一个合约进行交互时,可能并不清楚他是否实现了某些合约例如"ERC20\ERC721"等。所以可以先通过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 字节。有两种方式生成:

  1.  bytes4(keccak256('supportsInterface(bytes4)'));
  2. 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 {}
}

猜你喜欢

转载自blog.csdn.net/xq723310/article/details/130527131