从 A 到 Z 构建 ERC-20 代币(Hardhat + OpenZeppelin)

发布: (2025年12月18日 GMT+8 09:45)
6 min read
原文: Dev.to

Source: Dev.to

免责声明
仅用于教育目的。不是货币,没有内在价值,也未与任何现实世界的品牌或稳定币关联。

我写这篇文章的原因

许多进入加密领域的人会问相同的问题:

  • “为什么我的钱包里会出现一个随机代币?”
  • “为什么我看到余额却无法卖出?”
  • “ERC‑20 代币到底是如何创建的?”
  • “如果代币是假的,为什么它看起来很真实?”

真正理解这一点的最佳方式很简单:创建你自己的 ERC‑20 代币一次。当你这样做时,一切突然变得清晰:余额、钱包、授权、假代币、授权。

我们将构建的内容

我们将构建一个简洁的教育性 ERC‑20 代币,具备以下功能:

  • OpenZeppelin ERC‑20 实现
  • 基于角色的访问控制
  • 可暂停的转账
  • 铸造功能
  • 使用 Hardhat 部署
  • 将代币添加到 MetaMask
  • 了解钱包如何检测余额

1. 什么是 ERC‑20(通俗英文)

ERC‑20 不是一种货币。至少,ERC‑20 代币需要实现以下函数:

function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function totalSupply() external view returns (uint256);
function name() external view returns (string);
function symbol() external view returns (string);
function decimals() external view returns (uint8);

重要
代币必须拥有市场和流动性,才能产生价格和真实价值。没有流动性 → 没有价格 → 没有真实价值。

2. 环境搭建

要求

  • Node.js(LTS)
  • npm
  • MetaMask 钱包
  • Sepolia 测试 ETH
  • RPC 提供商(Alchemy、Infura 等)

创建项目

mkdir my-token
cd my-token
npm init -y
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox dotenv
npx hardhat

当出现提示时,选择 Create a JavaScript project

3. 安装 OpenZeppelin

OpenZeppelin 提供经过审计的、生产级别的智能合约。

npm install @openzeppelin/contracts

4. 编写 ERC‑20 代币合约

Create contracts/MyToken.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/*
    MyToken — an educational ERC-20 token.
    NOT money. NOT a stablecoin.
*/

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";

contract MyToken is ERC20, AccessControl, Pausable {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    constructor(uint256 initialSupply)
        ERC20("My Educational Token", "MYT")
    {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, msg.sender);
        _grantRole(PAUSER_ROLE, msg.sender);

        _mint(msg.sender, initialSupply);
    }

    function mint(address to, uint256 amount)
        external
        onlyRole(MINTER_ROLE)
    {
        _mint(to, amount);
    }

    function pause() external onlyRole(PAUSER_ROLE) {
        _pause();
    }

    function unpause() external onlyRole(PAUSER_ROLE) {
        _unpause();
    }

    function _update(address from, address to, uint256 amount)
        internal
        override
        whenNotPaused
    {
        super._update(from, to, amount);
    }
}

关键概念

  • namesymbol 只是字符串。
  • 合约存储余额。
  • 代币只有在被铸造后才存在。
  • 如果不铸造,余额将为零。

5. Hardhat 配置

创建(或编辑)hardhat.config.js

require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();

module.exports = {
  solidity: "0.8.20",
  networks: {
    sepolia: {
      url: process.env.SEPOLIA_RPC,
      accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
    },
  },
};

6. 环境变量

创建一个 .env 文件(切勿提交此文件):

SEPOLIA_RPC=https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY
PRIVATE_KEY=0xYOUR_PRIVATE_KEY

7. 部署脚本

const hre = require("hardhat");

async function main() {
  const [deployer] = await hre.ethers.getSigners();

  console.log("Deploying with address:", deployer.address);

  const initialSupply = hre.ethers.parseUnits("1000", 18);

  const MyToken = await hre.ethers.getContractFactory("MyToken");
  const token = await MyToken.deploy(initialSupply);

  await token.waitForDeployment();

  console.log("Token deployed at:", await token.getAddress());
}

main().catch(console.error);

8. 编译并部署

npx hardhat compile
npx hardhat run scripts/deploy.js --network sepolia

您将收到一个合约地址。

9. 将代币添加到 MetaMask

  1. 将 MetaMask 切换到 Sepolia 网络。
  2. 前往 Assets → Import Token
  3. 粘贴合约地址。MetaMask 会自动填充符号和小数位。

如果余额显示为 0,请检查:

  • 网络是否正确
  • 您铸造的地址是否实际收到了代币
  • 小数位设置
  • 重新加载 MetaMask(清除缓存)

10. 为什么代币会“凭空出现”

钱包 存储代币。钱包只是调用:

balanceOf(yourAddress)

因此,任何人都可以在未经请求或许可的情况下向你的地址铸造代币,而你的钱包仍会显示它们。

11. 为什么名称、符号和图标毫无意义

  • 没有全局的代币名称注册表。
  • 链上没有商标强制执行。
  • 没有“官方代币”标识。

任何人都可以部署一个合约,使用任意名称、符号、小数位或徽标。唯一可靠的代币标识是其合约地址

12. 核心安全教训

了解这些基础会让许多骗局变得显而易见:

  • “免费代币” → 无意义的余额
  • 假稳定币 → 只是带有好听名字的 ERC‑20 合约
  • 授权陷阱 → 危险的权限

知识胜过恐惧。

结论

ERC‑20 代币只是智能合约。创建自己的代币一次是最快了解余额、授权、铸造以及围绕它们的安全陷阱的方式。

Back to Blog

相关文章

阅读更多 »