diff --git a/EIPS/eip-165.md b/EIPS/eip-165.md new file mode 100644 index 00000000000000..250764ef6689b2 --- /dev/null +++ b/EIPS/eip-165.md @@ -0,0 +1,121 @@ +## Preamble + +``` +EIP: +Title: ERC-165 Standard Interface Detection +Author: Christian Reitwießner @chriseth, Nick Johnson @Arachnid, RJ Catalano @VoR0220, Fabian Vogelsteller @frozeman, Hudson Jameson @Souptacular, Jordi Baylina @jbaylina, Griff Green @griffgreen, William Entriken +Type: Standard Track +Category: ERC +Status: Draft +Created: 2018-01-23 +``` + +## Simple Summary + +Creates a standard method to publish and detect what interfaces a smart contract implements. + +## Abstract + +Herein, we standardize the following: + +1. How interfaces are identified +2. How a contract will publish the interfaces it implements +3. How to detect if a contract implements ERC-165 +4. How to detect if a contract implements any given interface + +## Motivation + +For some "standard interfaces" like [the ERC-20 token interface](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md), it is sometimes useful to query whether a contract supports the interface and if yes, which version of the interface, in order to adapt the way in which the contract is to be interfaced with. Specifically for ERC-20, a version identifier has already been proposed. This proposal stadardizes the concept of interfaces and standardizes the identification (naming) of interfaces. + +## Specification + +### How Interfaces are Identified + +For this standard, an *interface* is a set of [function selectors as calculated in Solidity](http://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector). This a subset of [Solidity's concept of interfaces](http://solidity.readthedocs.io/en/develop/abi-spec.html) and the `interface` keyword definition which also define return types, mutability and events. + +We define the interface identifier as the XOR of all function selectors in the interface. This code example shows how to calculate an interface identifier: + +```solidity +pragma solidity ^0.4.19; + +interface Solidity101 { + function hello() public pure; + function world(int) public pure; +} + +contract Selector { + function calculateSelector() public pure returns (bytes4) { + Solidity101 i; + return i.hello.selector ^ i.world.selector; + } +} +``` + +Note: interfaces do not permit optional functions, therefore, the interface identity will not them. + +### How a Contract will Publish the Interfaces it Implements + +A contract that is compliant with ERC-165 shall implement the following function: + +```solidity +pragma solidity ^0.4.19; + +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 + /// use less than 30000 gas. + /// @return `true` if the contract implements `interfaceID` and + /// `interfaceID` is not 0xffffffff, `false` otherwise + function supportsInterface(bytes4 interfaceID) external view returns (bool); +} +``` + +The interface identifier for this interface is `0x01ffc9a7`. You can calculate this by running ` bytes4(keccak256('supportsInterface(bytes4)'));` or using the `Selector` contract above. + +Therefore the implementing contract will have a `supportsInterface` function that returns: + +- `true` when `interfaceID` is `0x01ffc9a7` (EIP165 interface) +- `false` when `interfaceID` is `0xffffffff` +- `true` for any other `interfaceID` this contract implements +- `false` for any other `interfaceID` + +This function must return a bool and use at most 30000 gas. + +Implementation note, there are several logical ways to implement this function. Please see the example implementations and the discussion on gas usage. + +### How to Detect if a Contract Implements ERC-165 + +1. The source contact makes a `CALL` to the destination address with input data: `0x01ffc9a701ffc9a7` value: 0 and gas 30000. This corresponds to `contract.supportsInterface("0x01ffc9a7")`. +2. If the call fails or return false, the destination contract does not implement ERC-165. +3. If the call returns true, a second call is made with input data `0x01ffc9a7ffffffff`. +4. If the second call fails or returns true, the destination contract does not implement ERC-165. +5. Otherwise it implements EIP165. + +### How to Detect if a Contract Implements any Given Interface + +1. If you are not sure if the contract implements ERC-165 Interface, use the previous procedure to confirm. +2. If it does not implement ERC-165, then you will have to see what methods it uses the old fashioned way. +3. If it implements ERC-165 then just call `supportsInterface(interfaceID)` to determine if it implements an interface you can use. + +## Rationale + +We tried to keep this specification as simple as possible. This implementation is also compatible with the current Solidity version. + +## Backwards Compatibility + +The mechanism described above (with `0xffffffff`) should work with most of the contracts previous to this standard to determine that they do not implement ERC-165. + +Also [the ENS](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md) already implements this EIP. + +## Test Cases + +XXXXXXXX HELP NEEDED XXXXXXXXX + +## Implementation + +XXXXXX IN PROGRES XXXXXX [https://github.com/jbaylina/EIP165Cache](https://github.com/jbaylina/EIP165Cache) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).