3

Is there a way to get an interface ID of a Solidity interface using ethersjs? I'm using ethersjs in my test file and I want to test if the supportsInterface is returning a correct interface ID.

I could get the interface ID in Solidity with type(IMyContract).interfaceId but it doesn't seem like there is a straightforward way of achieving the same thing outside of Solidity.

How can I get the interface ID of a contract or interface in ethersjs?

4 Answers 4

4

Currently there is not. You have to xor all function selectors of IMyContract.

To make your life easier, you can use ethers.js interface and use its getSighash functions to not have to hash it and slice it ourself. But still you have to xor these selectors to get an interfaceId.

2
  • How do I xor the hashes in ethersjs? I don’t think I can use ^ to do that like in solidity.
    – xenon
    Commented Nov 11, 2021 at 11:52
  • 1
    No, you need to use BigNumber framework: ethers.BigNumber.from(foo1Selector).xor(ethers.BigNumber.from(foo2Selector)). Or at least thats how I do that.
    – ashhanai
    Commented Nov 12, 2021 at 16:15
7

Here's how I solved it, Ethers v5 & Typescript with OpenZeppelin upgradeable contracts (will work with any type of contract).


import { Contract, ContractInterface, ethers } from "ethers";
import { IERC1155Upgradeable__factory } from "../typechain-types/factories/IERC1155Upgradeable__factory";
import { IERC165Upgradeable__factory } from "../typechain-types/factories/IERC165Upgradeable__factory";

    const IERC165UpgradeableInterface = IERC165Upgradeable__factory.createInterface();
    const IERC1155UpgradeableInterface = IERC1155Upgradeable__factory.createInterface();
    const IERC165InterfaceID = getInterfaceID(IERC165UpgradeableInterface)
    // interface ID does not include base contract(s) functions.
    const IERC11InterfaceID = getInterfaceID(IERC1155UpgradeableInterface).xor(IERC165InterfaceID);
    assert(await contract.supportsInterface(IERC11InterfaceID._hex), "Doesn't support IERC1155Upgradeable");

export function getInterfaceID(contractInterface: ethers.utils.Interface) {
  let interfaceID: ethers.BigNumber = ethers.constants.Zero;
  const functions: string[] = Object.keys(contractInterface.functions);
  for (let i=0; i< functions.length; i++) {
      interfaceID = interfaceID.xor(contractInterface.getSighash(functions[i]));
  }

  return interfaceID;
}

The tricky part is that you have to xor out any base contracts as I looked though the solc compiler and they do not include base contract functions.

1
  • This is just an addition to @gvtopcoder sometimes the length of the the interfaceID._hex output is to short. you can add interfaceID._hex.padEnd(10, '0'). This will make sure that the supportsInterfaceInput is always correct.
    – rassenguy
    Commented Feb 10, 2023 at 12:53
2

If you do not mind to have a selector hardcoded, I would use the remix to get the selector. In particular, I would insert an interface of your contract into the remix and create another contract with a public variable with the type(IMyContract).interfaceId value assigned (see below). Then deploy the contract and get the value of the selector from the "DEPLOY & RUN TRANSACTIONS" panel.

Here is the workaround:

pragma solidity ^0.8.7;

interface IMyContract {
    function func1() external view returns (bytes32);
    function func2() external;
}

contract GetSelectorOfIMyContract {
    bytes4 public _interfaceId;
    constructor () {
        _interfaceId = type(IMyContract).interfaceId;
    }
}
1
  • thanks, it saved me tons of time & effort :)
    – Vanja Dev
    Commented Sep 13 at 22:11
0

I made a simple app to solve this problem(I had the same issue so i had to solve it). https://interfaceid.lucasgrasso.com.ar/ , You just have to paste the ABI of the Interface you want to have the ID to. Hope it´s useful.

1
  • 1
    Link only answers are discouraged. If the site stops working the answer isn't useful. It would be nice if you show the code used to generate the id.
    – Ismael
    Commented Oct 19, 2022 at 22:34

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.