从零开始,一文读懂以太坊Token的代码实现

 :2026-03-05 12:15    点击:2  

在区块链的世界里,代币(Token)无疑是应用最广泛、最具创新性的概念之一,它们不仅仅是数字货币,更是驱动去中心化应用(DApps)、治理协议、资产数字化等一切复杂逻辑的基础单元,而以太坊,凭借其智能合约平台的强大功能,成为了创建和发行代币的首选之地。

本文将带您深入以太坊代币的核心——代码,我们将从最经典的ERC-20标准开始,逐步解析其核心逻辑,并探讨其他重要的代币标准,让您对以太坊代币的代码实现有一个全面而清晰的认识。

以太坊代币的基石:ERC-20标准

如果你要创建一个以太坊上的代币,ERC-20是你绕不开的第一个名字,它不是一个官方的“法律”,而是一个技术标准,一个“行为准则”,任何遵循ERC-20标准的代币,都能保证与其他以太坊钱包、交易所和DApp完美兼容。

ERC-20标准定义了一系列智能合约必须实现的接口(函数和事件),下面,我们用最直观的方式,结合Solidity代码,来解读这些核心组成部分。

状态变量 - 代币的“身份证”

一个代币合约需要一些基本的“身份信息”:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract MyToken {
    // 1. 代币名称
    string public name = "My Awesome Token";
    // 2. 代币符号
    string public symbol = "MAT";
    // 3. 小数位数,用于精确计算 (18位,类似于以太坊)
    uint8 public decimals = 18;
    // 4. 总供应量,类型为uint256,可以表示非常大的数字
    uint256 public totalSupply;
    // 5. 余额映射,记录每个地址的代币余额
    // mapping(地址 => 余额)
    mapping(address => uint256) public balanceOf;
    // 6. 授权映射,记录每个地址被允许从另一个地址转移多少代币
    // mapping(授权人 => 被授权人 => 可授权额度)
    mapping(address => mapping(address => uint256)) public allowance;
}

代码解读:

  • namesymbol:就像比特币的“Bitcoin”和“BTC”,是代币的昵称和代码。
  • decimals:定义了代币可以被分割的最小单位,18位是目前最通用的标准,意味着总供应量会乘以 10^18 来表示最小单位。
  • totalSupply:代币的总发行量。
  • balanceOf:一个关键的“账本”,它用一个映射表记录了哪个地址拥有多少代币。
  • allowance:这是实现“授权转账”功能的核心,稍后会详细说明。

事件 - 合约的“广播站”

事件允许智能合约与外部世界进行通信,当某个重要操作发生时,合约可以“触发”一个事件,钱包、浏览器等外部应用可以“监听”这些事件,并做出相应反应(如更新UI)。

// 在合约中定义事件
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);

代码解读:

  • Transfer事件:每当代币被转账时触发。from是转出地址,to是转入地址,value是转账金额。indexed关键字使得这些参数可以被快速查询。
  • Approval事件:每当所有者授权某人花费其代币时触发。

核心函数 - 代币的“行为手册”

函数是代币合约的灵魂,定义了它可以执行的操作。

A. 转账函数

这是最基本的功能,将代币从一个地址转移到另一个地址。

/**
 * @dev 转账代币
 * @param _to 接收代币的地址
 * @param _value 转移的代币数量
 * @return bool 操作是否成功
 */
function transfer(address _to, uint256 _value) public returns (bool success) {
    // 1. 检查发送者是否有足够的余额
    require(balanceOf[msg.sender] >= _value, "ERC20: transfer amount exceeds balance");
    // 2. 更新余额:发送方减少,接收方增加
    balanceOf[msg.sender] -= _value;
    balanceOf[_to] += _value;
    // 3. 触发Transfer事件
    emit Transfer(msg.sender, _to, _value);
    // 4. 返回操作成功
    return true;
}

B. 授权与转账函数

这是一个非常实用的函数,想象一下,你在一个去中心化交易所(DEX)进行交易,你不需要先把代币转到交易所合约,而是可以授权交易所合约来“花费”你账户里的一定数量代币,这个过程就分两步:

  1. approve:你授权某个地址(如交易所)可以花费你的多少代币。
  2. transferFrom:被授权的地址调用这个函数,从你的账户里转移代币。
/**
 * @dev 授权某个地址可以花费你的代币
 * @param _spender 被授权的地址
 * @param _value 授权的金额
 * @return bool 操作是否成功
 */
function approve(address _spender, uint256 _value) public returns (bool success) {
    allowance[msg.sender][_spender] = _value;
    emit Approval(msg.sender, _spender, _value);
    return true;
}
/**
 * @dev 从某个地址转移代币(需要事先授权)
 * @param _from 代币转出的地址
 * @param _to 代币转入的地址
 * @param _value 转移的金额
 * @return bool 操作是否成功
 */
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
    // 1. 检查转出地址是否有足够余额
    require(balanceOf[_from] >= _value, "ERC20: transfer amount exceeds balance");
    // 2. 检查调用者是否有足够的授权额度
    require(allowance[_from][msg.sender] >= _value, "ERC20: insu
随机配图
fficient allowance"); // 3. 更新授权额度 allowance[_from][msg.sender] -= _value; // 4. 更新余额 balanceOf[_from] -= _value; balanceOf[_to] += _value; // 5. 触发Transfer事件 emit Transfer(_from, _to, _value); return true; }

C. 代币铸造与销毁

一个完整的代币合约还需要能够增加(铸造)和减少(销毁)总供应量,这通常只有合约所有者才能执行。

// 需要添加一个所有者地址
address public owner;
// 在构造函数中设置所有者
constructor() {
    owner = msg.sender;
}
/**
 * @dev 铸造新代币
 * @param _to 接收新代币的地址
 * @param _value 铸造的数量
 */
function mint(address _to, uint256 _value) public {
    // 只有所有者可以铸造
    require(msg.sender == owner, "ERC20: minting not allowed");
    // 增加总供应量和接收方余额
    totalSupply += _value;
    balanceOf[_to] += _value;
    // 触发Transfer事件,from地址为0x0...表示新币产生
    emit Transfer(address(0), _to, _value);
}
/**
 * @dev 销毁代币
 * @param _value 销毁的数量
 */
function burn(uint256 _value) public {
    // 检查发送者是否有足够余额
    require(balanceOf[msg.sender] >= _value, "ERC20: burn amount exceeds balance");
    // 减少总供应量和发送方余额
    totalSupply -= _value;
    balanceOf[msg.sender] -= _value;
    // 触发Transfer事件,to地址为0x0...表示币被销毁
    emit Transfer(msg.sender, address(0), _value);
}

超越ERC-20:其他重要的代币标准

虽然ERC-20是“万金油”,但不同的场景需要不同的代币标准。

  • ERC-721 (NFT标准):这是非同质化代物的标准,与ERC-20的“可互换”代币不同,ERC-721的每个代币都是独一无二的,就像艺术品的真迹一样,它的核心不再是balanceOf(余额),而是ownerOf(所有者),并且每个代币都有一个唯一的tokenId,著名的CryptoKitties就是基于ERC-721。

  • **ERC-1155 (多代币标准

本文由用户投稿上传,若侵权请提供版权资料并联系删除!