-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A standard for interface detection, fixes #165
- Loading branch information
1 parent
b943077
commit 5e02514
Showing
1 changed file
with
121 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
## Preamble | ||
|
||
``` | ||
EIP: <to be assigned> | ||
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 <github.com@phor.net> | ||
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/). |