# 🚀 Solidity从零到一:手把手教你开发ERC-20代币

3 阅读1分钟

🔧 开发环境准备

1. 安装必要工具

【安装Node.js和npm】
npm install -g truffle

【安装Ganache(本地测试链)】
npm install -g ganache-cli

2. 创建项目

mkdir my-token && cd my-token
truffle init
npm install @openzeppelin/contracts

💻 编写智能合约

1. 创建代币合约

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

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyToken is ERC20, Ownable {
    constructor() ERC20("My Token", "MTK") {
        _mint(msg.sender, 1000000 * 10 ** decimals());
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }
}

2. 合约代码解析

  • ERC20标准:实现代币基本功能
  • Ownable:添加权限控制
  • decimals():设置小数位数(默认18)
  • _mint():初始发行代币

🧪 测试与部署

1. 编写测试用例

const MyToken = artifacts.require("MyToken");

contract("MyToken", accounts => {
    it("should have correct name and symbol", async () => {
        const instance = await MyToken.deployed();
        const name = await instance.name();
        const symbol = await instance.symbol();

        assert.equal(name, "My Token");
        assert.equal(symbol, "MTK");
    });
});

2. 部署到测试网

// truffle-config.js 配置
module.exports = {
  networks: {
    ropsten: {
      provider: () => new HDWalletProvider(
        process.env.MNEMONIC,
        `https://ropsten.infura.io/v3/${process.env.INFURA_API_KEY}`
      ),
      network_id: 3,
      gas: 5500000,
      confirmations: 2,
      timeoutBlocks: 200,
      skipDryRun: true
    }
  }
};

🔒 安全注意事项

1. 常见漏洞

  • 重入攻击:使用Checks-Effects-Interactions模式
  • 整数溢出:使用SafeMath或Solidity 0.8+
  • 权限控制:合理使用onlyOwner修饰符

2. 最佳实践

  • 使用OpenZeppelin安全合约库
  • 进行完整的单元测试
  • 使用形式化验证工具

🎯 进阶功能

1. 添加销毁功能

function burn(uint256 amount) public {
    _burn(msg.sender, amount);
}

2. 时间锁功能

import "@openzeppelin/contracts/security/Pausable.sol";

contract MyToken is ERC20, Ownable, Pausable {
    // 添加暂停功能
}

📊 实战项目:创建一个代币空投DApp

前端代码示例(React)

import { ethers } from 'ethers';
import { useEffect, useState } from 'react';

function TokenAirdrop() {
    const [balance, setBalance] = useState('0');

    const claimAirdrop = async () => {
        const provider = new ethers.providers.Web3Provider(window.ethereum);
        const signer = provider.getSigner();
        const contract = new ethers.Contract(
            tokenAddress,
            tokenABI,
            signer
        );

        const tx = await contract.transfer(msg.sender, ethers.utils.parseEther('100'));
        await tx.wait();
        alert('空投领取成功!');
    };