Some questions about Interface ids

:1234: Code to reproduce

Contract A

pragma solidity >= 0.8.0;

import "";
import "";
import "";
import "";

contract ContractA is ERC165 {

    constructor() {}

    function supportsInterface(bytes4 interfaceID) public view override returns (bool){
        return interfaceID == 0x12345678;

    function getInterface0() external view returns (bytes4) {
        return type(ERC165).interfaceId;

    //function getInterface1() external view returns (bytes4) {
    //    return type(ERC20).interfaceId;

    //function getInterface2() external view returns (bytes4) {
    //    return type(ERC721).interfaceId;

    function getInterface3() external view returns (bytes4) {
        return type(IERC20).interfaceId;


import "./ContractA.sol";

contract ContractB is ContractA {

    constructor() {}

    function getInterface01() external view returns (bytes4) {
        return type(ContractA).interfaceId;



I just study a bit about interfaceIds...
And got some question about it. Hopefully someone here can help me out.
In the docs ( is written that you can access an interface id with "type(Contract).interfaceId"


  1. It works for me with ERC165 contract but not with ERC20.
  2. But it works for IERC20...
  3. I do not see any implementation in any contract of "interfaceId".
  4. I fail at the try to implement my own id. (In ContractA i can manipulate the return value of "supportsInterface" - but that does not make it possible to compile "type(ContractA).interfaceId" ->

TypeError: Member "interfaceId" not found or not visible after argument-dependent lookup in type(contract ContractA).

So my questions would be:

  1. Why does some contracts have the id (ERC165 return of "getInterface0()") and some not (ERC20 - even when ERC20 is IERC20)?
  2. How does eg. IERC20 get an id?
    2.1. My own interfaces gets also an id - but how? Can I manipulate them?