ERC875-Example-Implementation icon indicating copy to clipboard operation
ERC875-Example-Implementation copied to clipboard

Support ERC165?

Open hboon opened this issue 7 years ago • 6 comments
trafficstars

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md

hboon avatar Oct 05 '18 17:10 hboon

It surely makes sense imho. Does ERC875 need to explicitly say that it supports 165, or is it inexplicit?

SmartLayer avatar Oct 06 '18 02:10 SmartLayer

Does eRC875 need to explicitly say that it supports 165, or is it inexplicit?

I'm not sure what you mean.

But this is what's needed:

pragma solidity ^0.4.20;

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
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

A simple way to implement the supportsInterface() is just a couple of if-else to return true when interfaceID equals 0x01ffc9a7 (hence supporting ERC165 itself) or the hash for ERC875 (trivial to precompute, by xor-ing every function selector in ERC875):

ie.

bytes4(keccak256('name()')) ^ 
    bytes4(keccak256('symbol()')) ^ 
    bytes4(keccak256('balanceOf(address)')) ^ 
    bytes4(keccak256('transfer(address,uint256[])')) ^ 
    bytes4(keccak256('transferFrom(address,address,uint256[])')) ^ 
    bytes4(keccak256('name()'))

And maybe an additional hash for the above xor-ed with the optional functions.

James and I were talking about how ERC165 is limited because it can't be used to check if you have a subset of the functions implemented [1]. This can happen with optional functions or when an ERC implemented before it is finalized. Eg. CryptoKitties interface hash for ERC721 is a different value from the current ERC721's.

[1] It's not impossible, we just have to implement supportsInterface() and return true for every xor of every combination of 1-n function selectors. So 63 (6+15+20+15+6+1 I think) hashes for ERC875's 6 functions? So still probable for a handful of functions. And let everyone know that this is supported since ERC165 doesn't mention this.

hboon avatar Oct 06 '18 08:10 hboon

@hboon anyone u need to assign the task?

miang719 avatar Oct 26 '18 03:10 miang719

@miang719 I suppose @James-Sangalli.

So ERC165 is easy to support and we can and I think we should.


There's room for something better, maybe as a separate issue. As a wallet app, we tend to work with all kinds of tokens, so this is quite relevant to us. How feasible is it to just flip the check around, instead of querying by calling a function like supportsInterface("0x80ac58cd"), can't we just implement a function to return the entire list of public functions?:

string[] public funs;

constructor () public {
    funs = [
        "balanceOf(address)",
        "ownerOf(uint256)",
        "safeTransferFrom(address,address,uint256,bytes)",
        //List every public function
    ];
}

function supportedFunctions() public view returns (string[]) {
    return funs;
}

ERC165 is easy to implement wrongly (outdated hash, wrong hash), support for optional interfaces/functions is ambiguous and doesn't support querying for a subset of an interface or a specific function. On the other hand, a single function that returns everything that is supported seems so much better.

hboon avatar Oct 26 '18 05:10 hboon

Added but not implemented, can make it optional for whatever token standard

Edit: This is subjective to each contract that uses eip875 as it may have other functions

JamesANZ avatar Nov 03 '18 18:11 JamesANZ

@James-Sangalli maybe we should state the interface ID for xor-ing the mandatory functions for ERC875 here https://github.com/AlphaWallet/ERC875-Example-Implementation/blob/master/ERCTokenImplementation.sol#L8? Reduce the chance of implementors getting it wrong:

function name() constant public returns (string name);
function symbol() constant public returns (string symbol);
function balanceOf(address _owner) public view returns (uint256[] _balances);
function transfer(address _to, uint256[] _tokens) public;
function transferFrom(address _from, address _to, uint256[] _tokens) public;

hboon avatar Nov 04 '18 14:11 hboon