世界杯竞猜项目Dapp-第三章(ERC20)

ERC20 是标准的以太坊 Token 协议,它也是一个合约代码,只要在该合约内部实现了特定的 6 个方法,就会被系统判定为代币合约,具体总结为:6 个必要接口,2 个必要事件,3 个可选接口,详情如下:

6 个必要接口

// 代币总发行量
function totalSupply() public view returns(uint256)

// 内部维护一个 mapping,返回余额
function balanceOf(address _owner) public view returns(uint 256 balance)

// token 持有人调用,进行转账(写操作,花钱)
// 张三 -> 李四, 100 * 10**18
function transfer(address _to, uint256 _value) public returns(bool success)

// 张三是 token 持有人, 作为 owner, 1w
// 张三将 1w 授权给李四
function approve(address _spender, uint256 _value) public returns(bool success)
allowanace[张三][李四] += 1w

function allowance(address _owner, address _spender) public view returns (uint256 remaining)
// 李四是被授权人,spender
// 王五是接受 token 的人,receiver

// 李四是张三的授权人,李四调用 transferFrom 给王五转账
function transferFrom(address _from, address _to, uint256 _value) public returns(bool success)

2 个必要事件

// 在tranfer 和transferFrom内部使用
event Transfer(address indexed _from, address indexed _to, uint256 _value)

// 在approve方法中使用
event Approval(address indexed _owner, address indexed _spender, uint256 _value)

3 个可选接口

// Token 名称
function name() public view returns (string)

// Token 标识,比如 ETH
function symbol() public view returns (string) 

// USDT:  6, 10000000 * 10**6
// WBTC:  8, 10000000 * 10**8
// 其他Token:18, 10000000 * 10**18
// 精度
function decimals() public view returns (uint8)

常见使用场景

  • 张三为 Token 持有人,李四为张三的委托人(被授权),王五是收款人
  • 张三调用 USDT 的 Approve 方法,授权李四可以支配 50w Token,调用格式为:USDT.Approve(李四, 50w)
  • 此时在 USDT 合约内部,会通过 allowance 进行记录:allowance[张三][李四] += 50w
  • 此时李四便可以支配张三的 50w USDT,并调用 transferFrom 给王五转转,调用形式为:USDT.transferFrom(张三, 王五, 1w)
  • 转账过后,张三的 Token 减少 1w,王五点 Token 增加 1w,李四被授权的额度减少 1w

实战发行 ERC20 Token

我们发行一个 worldCupToken,用于后续对参与竞猜的用户进行奖励,token信息如下:

  • Name:World Cup Token
  • Symbol:WCT
  • Decimals:18
  • TotalSupply:1w
    首先在 node_modules 目录下安装标准 openzeppeline 包以引入 ERC20
npm i @openzeppelin/contracts

创建 WorldCupToken.sol,如下:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

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

contract WorldCupToken is ERC20 {
    // 一次性 mint 出来,不允许后续 mint
    // name:名称,symbol:token 标识,toalSupply:总发行量
    constructor(
        string memory name_,
        string memory symbol_,
        uint256 totalSupply_
    ) ERC20(name_, symbol_) {
        _mint(msg.sender, totalSupply_);
    }
}

创建部署脚本 deployMockERc20.ts

import { ethers } from "hardhat";

async function main() {

  const totalSupply = ethers.utils.parseUnits('10000000', 18)
  console.log('totalSupply:', totalSupply);

  const FHTToken = await ethers.getContractFactory('WorldCupToken');
  const fht = await FHTToken.deploy("World Cup Token", "WCT", totalSupply);

  await fht.deployed();

  console.log(`new World Cup Token deployed to ${fht.address}`);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

编译部署合约:

# new World Cup Token deployed to 0x8fe664FA864C61054D2dec3dEB54b204a427d8A8
npx hardhat run scripts/deployMockERc20.ts --network goerli

// verify
npx hardhat verify --contract contracts/WorldCupToken.sol:WorldCupToken 0x8fe664FA864C61054D2dec3dEB54b204a427d8A8 "World Cup Token" "WCT" "10000000000000000000000000" --network goerli
posted @ 2022-12-13 15:51  这个杀手冷死了  阅读(24)  评论(0编辑  收藏  举报