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.
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.
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.
// 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.