0

Like we know that the receiver contract can provide the confirmation of the implemented interfaces by comparing the interface indentifier and function selector of implemented interfaces.

What could go wrong in case of Function selector collision, where the caller contract gets a false confirmation due to it

2 Answers 2

0

Function selectors are a Solidity concept. The code it emits basically does a switch statement and jumps to the right function.

If you have a collision of function selectors, the Solidity compiler raises an error. If you skip the Solidity compiler and write your own bytecode that makes use of function selectors, you'll just have to decide what to do yourself. (You can make the code do whatever you want.)

The rest of the system does not care about function selectors or how your contract behaves in those cases.

Its already answered here: How does the EVM resolve method ID collision?

I couldn't post in comments because don't have enough reputation for that

0

Short answer:

Absolutely everything and anything can go wrong if you rely on ERC165 to tell you whether some contract correctly and safely implements any given interface. This is because contracts can implement ERC165 and lie (both false positives and false negatives), either accidentally or deliberately.

Longer answer:

ERC165 is an ethereum concept, not Solidity specific as the other answer states.

https://eips.ethereum.org/EIPS/eip-165

How Interfaces are Identified For this standard, an interface is a set of function selectors as defined by the Ethereum ABI. This a subset of Solidity’s concept of interfaces and the interface keyword definition which also defines 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

The ERC165 interface only defines interface detection.

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);
}

So the premise of the question, that both the interface identifier and function selectors are checked, is wrong.

The interface ID is all the function selectors in a given interface, combined to a single value. The interface check doesn't support individual function checks.

There may be a collision between two unrelated interfaces, as the interface ID is only 4 bytes, which only gives about 4 billion possible values (2^32). If for some reason there was a way to profit from brute forcing an interface collision then someone absolutely could do so.

The question here though, is about what could go wrong when calling a contract based on there being a collision. Not about how the interface ID is defined.

There's kind of two answers to this.

One answer is that a collision accidentally on the XOR of all the function signatures within two different interfaces, probably doesn't imply any overlap at all in the individual functions. This is because each function signature is hashed to build the selector, so including any function into the interface id randomly changes roughly half the bits.

This means that probably when you attempt to call any of the functions by their selector, based on a false positive from ERC165, the function simply won't be found on that contract. The two colliding interfaces probably have completely unrelated functions composing their interface IDs. What happens next is up to that contract. It MAY revert when asked to execute a selector it knows nothing about, or it MAY do arbitrarily anything it all and NOT revert.

Which leads to the second answer. Which is that if there is a deliberate attempt to create a collision, it is easy to do so. e.g. by building interfaces out of functions with 0 valued selectors, as can be found in online signature databases signature database screenshot of 0x00000000 selector functions https://openchain.xyz/signatures?query=0x00000000

This is because 0 ^ x = x. Probably you should be suspicious if someone is deliberately crafting collisions, as to what their motives might be.

This highlights issue behind the original question, which is that calling a contract is a trust/verification question. You can't trust anything about a contract based on ERC165, whether an interface check returns true or false. A contract can lie either way. There being a collision with some other interface is just a specific case of when a contract might lie about its interface. Even if a contract exposes all the correct functions, that doesn't mean the implementation of those functions can be trusted.

ERC165 is a discovery mechanism, it highlights candidate contracts out of a sea of otherwise undifferentiated bytecode. This is useful for building certain tools but is useless for deciding which contracts are safe to call. It's up to EOAs to verify that the contracts on the other side of that discovery mechanism are trustworthy or not, interface collision or no.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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