solidity dapp ERC-165

The ERC-165 standard is used to publish and detect which interfaces are implemented by smart contracts.

When we need to interact with a contract, it may not be clear whether he has implemented certain contracts such as "ERC20\ERC721" and so on. So you can first query through Erc165 (the contract must implement ERC165), and you can avoid many interaction problems.

ERC165 standard

 The ERC165 standard is an interface, and there is a method in it - supportsInterface; users can call this method and input the corresponding interface ID to query whether the contract implements the corresponding interface ID;

interface IERC165 {
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

The ERC165 interface ID is 0x01ffc9a7;

How is the interface ID calculated?

        An interface is a set of function selectors defined by the Ethereum ABI. The function selector is the first 4 bytes of the Keccak (SHA-3) hash of the function signature (eg "myMethod(uint256,string)"). There are two ways to generate:

  1.  bytes4(keccak256('supportsInterface(bytes4)'));
  2. supportsInterface(bytes4).selector

        The interface ID (interface identifier) ​​is defined as the exclusive OR (XOR) of all function selectors in the interface. In the following example, the interface ID of Animal is calculated by the calculateSelector function.

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;

    }

}

How and how to apply it?

        Let's continue to use the example of Animal. We have implemented two contracts, Dog and Cat respectively, both of which implement the Animal and IERC165 interfaces; the methods are slightly different,

        Dog uses the pure (pure function) implementation of supportsInterface. The worst-case execution cost is 236 gas, but the gas increases linearly with the number of supported interfaces.

        Cat This method is implemented using the view (view function) of supportsInterface. The execution cost for any input is 586 gas. But the contract initialization needs to store each interface (SSTORE is 20,000 gas). The ERC165MappingImplementation contract is generic and reusable.

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 {}
}

Guess you like

Origin blog.csdn.net/xq723310/article/details/130527131