🔧 开发环境准备
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. 部署到测试网
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('空投领取成功!');
};