Interfaces

Define the shape of a contract without its implementation — the key to composable DeFi.

What is an interface?

An interface declares a contract's external API — its function signatures — without any implementation. This lets you call functions on a contract at a known address without knowing or caring about its internal code.

solidity
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address from, address to, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

Calling an external contract via interface

Once you have an interface, you can call any contract that implements it by wrapping its address.

solidity
contract LiquidityManager {
    function depositToken(address tokenAddress, uint256 amount) external {
        IERC20 token = IERC20(tokenAddress);

        // Pull tokens from the caller into this contract
        require(
            token.transferFrom(msg.sender, address(this), amount),
            'Transfer failed'
        );
    }
}

Interface rules

  • All functions must be external
  • No state variables
  • No constructors
  • No function implementations (no curly braces with code)
  • Can declare events and errors

Standard interfaces you'll use constantly

The Ethereum ecosystem has standardized several critical interfaces. Knowing them is non-negotiable for DeFi development.

solidity
// ERC-20: Fungible tokens
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';

// ERC-721: Non-fungible tokens
import '@openzeppelin/contracts/token/ERC721/IERC721.sol';

// Uniswap V2 core interfaces
interface IUniswapV2Pair {
    function getReserves() external view returns (
        uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast
    );
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
}

interface IUniswapV2Router02 {
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
}

Interfaces enable composability

This is DeFi's superpower. Because all contracts that follow the same interface can be called the same way, protocols can compose on top of each other without needing access to each other's source code. A lending protocol can accept any ERC-20 as collateral. A DEX aggregator can route through any Uniswap V2-compatible pool. This is the money lego model.

←   Inheritance and abstract contractsSending and receiving Ether   →