接口 #

一、接口概述 #

1.1 什么是接口 #

接口定义了合约的外部API,是一组函数签名的集合,不包含实现。

solidity
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address owner) external view returns (uint256);
    function transfer(address to, uint256 value) external returns (bool);
}

1.2 接口的作用 #

作用 说明
定义标准 如ERC20、ERC721等标准
合约交互 调用其他合约的函数
类型安全 确保函数签名正确
文档化 明确合约的外部API

二、接口定义 #

2.1 基本语法 #

solidity
interface InterfaceName {
    function functionName(parameters) external returns (returnTypes);
}

2.2 接口限制 #

solidity
interface IExample {
    // ✓ 允许:函数声明
    function getValue() external view returns (uint256);
    
    // ✓ 允许:事件声明
    event ValueChanged(uint256 newValue);
    
    // ✗ 不允许:状态变量
    // uint256 value;
    
    // ✗ 不允许:构造函数
    // constructor() {}
    
    // ✗ 不允许:函数实现
    // function foo() external { }
    
    // ✗ 不允许:修饰器
    // modifier onlyOwner() { _; }
}

2.3 接口示例 #

solidity
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address owner) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);
    
    function transfer(address to, uint256 value) external returns (bool);
    function approve(address spender, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);
    
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface IERC721 {
    function balanceOf(address owner) external view returns (uint256);
    function ownerOf(uint256 tokenId) external view returns (address);
    function transferFrom(address from, address to, uint256 tokenId) external;
    function approve(address to, uint256 tokenId) external;
    
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
}

三、接口实现 #

3.1 实现接口 #

solidity
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address owner) external view returns (uint256);
    function transfer(address to, uint256 value) external returns (bool);
}

contract MyToken is IERC20 {
    uint256 private _totalSupply;
    mapping(address => uint256) private _balances;
    
    constructor(uint256 supply) {
        _totalSupply = supply;
        _balances[msg.sender] = supply;
    }
    
    function totalSupply() external view override returns (uint256) {
        return _totalSupply;
    }
    
    function balanceOf(address owner) external view override returns (uint256) {
        return _balances[owner];
    }
    
    function transfer(address to, uint256 value) external override returns (bool) {
        require(_balances[msg.sender] >= value, "Insufficient balance");
        _balances[msg.sender] -= value;
        _balances[to] += value;
        return true;
    }
}

3.2 多接口实现 #

solidity
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function transfer(address to, uint256 value) external returns (bool);
}

interface IERC20Metadata {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
}

contract MyToken is IERC20, IERC20Metadata {
    string private _name;
    string private _symbol;
    uint8 private _decimals;
    uint256 private _totalSupply;
    
    mapping(address => uint256) private _balances;
    
    constructor(
        string memory name_,
        string memory symbol_,
        uint8 decimals_,
        uint256 totalSupply_
    ) {
        _name = name_;
        _symbol = symbol_;
        _decimals = decimals_;
        _totalSupply = totalSupply_;
        _balances[msg.sender] = totalSupply_;
    }
    
    function name() external view override returns (string memory) {
        return _name;
    }
    
    function symbol() external view override returns (string memory) {
        return _symbol;
    }
    
    function decimals() external view override returns (uint8) {
        return _decimals;
    }
    
    function totalSupply() external view override returns (uint256) {
        return _totalSupply;
    }
    
    function transfer(address to, uint256 value) external override returns (bool) {
        require(_balances[msg.sender] >= value, "Insufficient balance");
        _balances[msg.sender] -= value;
        _balances[to] += value;
        return true;
    }
}

四、接口使用 #

4.1 调用其他合约 #

solidity
interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);
    function balanceOf(address owner) external view returns (uint256);
}

contract TokenUser {
    IERC20 public token;
    
    constructor(address tokenAddress) {
        token = IERC20(tokenAddress);
    }
    
    function transferTokens(address to, uint256 amount) public returns (bool) {
        return token.transfer(to, amount);
    }
    
    function getBalance(address owner) public view returns (uint256) {
        return token.balanceOf(owner);
    }
}

4.2 类型转换 #

solidity
interface IERC20 {
    function totalSupply() external view returns (uint256);
}

contract InterfaceCast {
    function getTotalSupply(address tokenAddress) public view returns (uint256) {
        IERC20 token = IERC20(tokenAddress);
        return token.totalSupply();
    }
}

五、常见标准接口 #

5.1 ERC20接口 #

solidity
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, 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 sender, address recipient, 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);
}

5.2 ERC721接口 #

solidity
interface IERC721 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
    
    function balanceOf(address owner) external view returns (uint256 balance);
    function ownerOf(uint256 tokenId) external view returns (address owner);
    function safeTransferFrom(address from, address to, uint256 tokenId) external;
    function transferFrom(address from, address to, uint256 tokenId) external;
    function approve(address to, uint256 tokenId) external;
    function getApproved(uint256 tokenId) external view returns (address operator);
    function setApprovalForAll(address operator, bool _approved) external;
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

5.3 ERC165接口 #

solidity
interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

contract MyNFT is IERC165 {
    function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC165).interfaceId;
    }
}

六、最佳实践 #

6.1 接口命名 #

solidity
// 推荐:使用I前缀
interface IERC20 {}
interface IERC721 {}
interface IAccessControl {}

// 推荐:使用大驼峰
interface ITokenReceiver {}

6.2 接口分离 #

solidity
// 推荐:分离核心接口和扩展接口
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
}

interface IERC20Metadata {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
}

七、总结 #

接口要点:

特性 说明
定义 interface InterfaceName { ... }
函数 只声明,不实现
事件 可以声明
实现 使用is关键字
限制 无状态变量、构造函数、实现

使用建议:

  • 使用接口定义标准
  • 使用I前缀命名
  • 分离核心和扩展接口
  • 实现标准接口确保兼容性

接下来,让我们学习多态!

最后更新:2026-03-27