5

Given a valid contract address how can I check if the contract implemented a certain interface i.e Ownable?

4

ERC165 tackles this problem but it cannot be used for older ERCs. For instance, most ERC20 implementations don't implement it (as of Nov 2018, at least OpenZeppelin doesn't). You could try calling the supportsInterface function, but it would revert and you'd rather complicate things.

However, here's how it's defined in ERC721:

bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd;
/*
 * 0x80ac58cd ===
 *   bytes4(keccak256('balanceOf(address)')) ^
 *   bytes4(keccak256('ownerOf(uint256)')) ^
 *   bytes4(keccak256('approve(address,uint256)')) ^
 *   bytes4(keccak256('getApproved(uint256)')) ^
 *   bytes4(keccak256('setApprovalForAll(address,bool)')) ^
 *   bytes4(keccak256('isApprovedForAll(address,address)')) ^
 *   bytes4(keccak256('transferFrom(address,address,uint256)')) ^
 *   bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
 *   bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
 */

It's not guaranteed that all implementations define the interface id, but there's a good chance that ERC721s do it, since the community agreed on applying ERC165 right from the get-go. If the return value of the query below is true, then it means you have a compliant contract, otherwise just revert the transaction.

// you can call this in your contracts
IERC721(contractAddress).supportsInterface(0x80ac58cd)

Also, a useful resource for manually checking the bytes4 of a given method is 4byte.directory

| improve this answer | |
0

Simply make a transaction using the supposed ABI to the contract and watch the answer. If it succeeds, do not take for assured the interface presence, but test some ancillary supposed methods in order to assess (i.e. if it answer to a totalSupply query, it does not assure you that a real totalSupply() method do exist, but if the result of the method called are consistent, you can use it).

As answered before, there it exists EIP proposal to solve this.

| improve this answer | |
0

You could try to call the contract method owner() using solidity's call, staticcall or directly using asembbly, this link explains it better https://medium.com/@blockchain101/calling-the-function-of-another-contract-in-solidity-f9edfa921f4c

Solidity's call has issues with bytes and string types. Solidity's author, chriseth, recommends to avoid using it. https://github.com/ethereum/solidity/issues/2884#issuecomment-329169020 This was fixed in https://github.com/ethereum/solidity/issues/4652#issuecomment-411712839 see solidity specifications for solidity 0.5.0 https://solidity.readthedocs.io/en/v0.5.0/050-breaking-changes.html#semantic-and-syntactic-changes

Soliditi's StaticCall is the same as call but it would throw an error if tries to change state, this is great to avoid reentrancy attacks https://github.com/ethereum/EIPs/pull/214/files

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.