Solidity Interfaces – How They Know Which Contract They Are Interfacing

addresseserc-20interfacesremixsolidity

To my understanding, an address at some point needs to be provided so that the name of the interface that you write in your code is linked to the existing external contract you want to interface with. However, I don't see an address being provided in the code of a lot of popular ERC20 tokens interfacing the ERC20 contract, for instance with Axie Infinity:

INTERFACE DELCARATION:

// File: token/erc20/ERC20.sol

pragma solidity 0.5.17;

contract ERC20 is IERC20 {
  using SafeMath for uint256;

  uint256 public totalSupply;
  mapping (address => uint256) public balanceOf;
  mapping (address => mapping (address => uint256)) internal _allowance;

  function approve(address _spender, uint256 _value) public returns (bool) {
    _approve(msg.sender, _spender, _value);
    return true;
  }

...

Source Code:
https://etherscan.io/address/0xbb0e17ef65f82ab018d8edd776e8dd940327b28b#code

I did a Control + F for 0x in the source code, and apparently no addresses are written inside, which leads me to believe there is a step I'm missing where the addresses are written inside.

I noticed that the URL to the ERC20 token file is commented out, so does that mean an address wasn't needed in this case but rather the complier knew somehow that the file was located in:

token/erc20/ERC20.sol

However all the references to that address were commented out and not used as parameters in any function call.

The only other thing I was able to find was in the solidity documents referencing needing to reference libraries using the Commandline Complier for linking, and in this case it was talking about libraries and not interfaces (so not even sure if this is relevant):

As the compiler cannot know where the library will be deployed at,
these addresses have to be filled into the final bytecode by a linker
(see Using the Commandline Compiler for how to use the commandline
compiler for linking). If the addresses are not given as arguments to
the compiler, the compiled hex code will contain placeholders of the
form Set____ (where Set is the name of the library). The address
can be filled manually by replacing all those 40 symbols by the hex
encoding of the address of the library contract.

source: https://docs.soliditylang.org/en/v0.4.24/contracts.html?highlight=library#libraries

MY QUESTION:

How then do contracts then link the interface objects they are making in their contracts with the external contract they are interfacing? I'm sure there might be a few ways to do it, feel free to walk through whichever ways you know and explain it to me like I was a newbie, which I admittedly am.

Best Answer

You are mixing up two different concepts: implementing an interface and casting an address to an interface.

The ERC20 snippet you provided is a contract that implements an interface, i.e. inherits from it and defines functions that satisfy the requirements of that interface. This contract must be compiled and deployed to give it an actual address on the blockchain. You then publish/share the address and the interface definition in some way.

With that information anyone can import the interface definition and cast the address to it.:

import "IERC20.sol";

...

function bar() {
    IERC20 token = IERC20(address(0x1234567890123456789012345678901234567890));
    token.foo(x, y, z);
}

I noticed that the URL to the ERC20 token file is commented out, so does that mean an address wasn't needed in this case but rather the complier knew somehow that the file was located in:

I think this comment was inserted by a tool that flattened the contract for verification (i.e. combined multiple files belonging to the project into a single, equivalent one). It just tells you in which file this piece of code originally resided. The compiler does not modify your source.

The only other thing I was able to find was in the solidity documents referencing needing to reference libraries using the Commandline Complier for linking, and in this case it was talking about libraries and not interfaces (so not even sure if this is relevant):

This is related but, as you noticed, it's only for libraries not interfaces. There can be multiple contracts that satisfy a given interface and you can choose one at runtime by specifying the address. With libraries there's only one implementation and you provide its address on the command line as an argument for the compiler so that it can be hard-coded in the compiled bytecode. This is why, when you define a library called, say, L, you can refer to it as just L and not L(address(0x...)).

Related Topic