Skip to main content

Command Palette

Search for a command to run...

智能合约实例-5: 发行erc20代币

Published
3 min read

智能合约工程师, 业余Youtuber, 投机套利爱好者.

ERC20 代币

任何遵循ERC20 标准的合约都是 ERC20 代币。

ERC20 标准: https://eips.ethereum.org/EIPS/eip-20

实现功能

ERC20 代币提供以下功能

  • 转移代币
  • 允许其他人代表代币持有者转移代币

接下来查看, ERC20的具体实现.

代码讲解

  • ERC20 的标准接口
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/token/ERC20/IERC20.sol
interface IERC20 {

    // 总供应量
    function totalSupply() external view returns (uint);

    // 某地址的余额
    function balanceOf(address account) external view returns (uint);


    // 转移 Token
    function transfer(address recipient, uint amount) external returns (bool);

    // 返回spender仍然允许提取的金额
    function allowance(address owner, address spender) external view returns (uint);

    // 授权spender 及金额数量
    function approve(address spender, uint amount) external returns (bool);

    // 该transferFrom方法用于提款工作流程,允许合约代表你转移代币。
    function transferFrom(
        address sender,
        address recipient,
        uint amount
    ) external returns (bool);

    // 触发事件: 转移代币
    event Transfer(address indexed from, address indexed to, uint value);

    // 触发事件: 授权代币
    event Approval(address indexed owner, address indexed spender, uint value);
}
  • ERC20 的代币合约示例

查看一个完整的代币发行合约, 需要实现那些函数和功能, 让其符合ERC20 标准.

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

import "./IERC20.sol";

contract ERC20 is IERC20 {
    uint public totalSupply;
    mapping(address => uint) public balanceOf;
    mapping(address => mapping(address => uint)) public allowance;
    string public name = "Solidity ERC20 Test";
    string public symbol = "SET";
    uint8 public decimals = 18;

    function transfer(address recipient, uint amount) external returns (bool) {
        balanceOf[msg.sender] -= amount;
        balanceOf[recipient] += amount;
        emit Transfer(msg.sender, recipient, amount);
        return true;
    }

    function approve(address spender, uint amount) external returns (bool) {
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    function transferFrom(
        address sender,
        address recipient,
        uint amount
    ) external returns (bool) {
        allowance[sender][msg.sender] -= amount;
        balanceOf[sender] -= amount;
        balanceOf[recipient] += amount;
        emit Transfer(sender, recipient, amount);
        return true;
    }

    // 铸造新的token 
    function mint(uint amount) external {
        balanceOf[msg.sender] += amount;
        totalSupply += amount;
        emit Transfer(address(0), msg.sender, amount);
    }

    // 销毁token 数量
    function burn(uint amount) external {
        balanceOf[msg.sender] -= amount;
        totalSupply -= amount;
        emit Transfer(msg.sender, address(0), amount);
    }
}

实战案例

  • 创建自己的ERC20 的最佳实践

使用Open Zeppelin: https://github.com/OpenZeppelin/openzeppelin-contracts

这是一个智能合约代码仓库, 它帮我们实现了大部分合约的细节, 并且确保了合约的安全性.

通过使用Open Zeppelin,创建自己的 ERC20 代币真的很容易。

这是一个例子

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

// 导入Github 上的源代码 
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.0.0/contracts/token/ERC20/ERC20.sol";

// 继承 Open Zeppelin 的 ERC20 , 它帮我们实现了所有 ERC20标准的细节. 

contract MyToken is ERC20 {

    // 初始化, Token 的名称符号, 发行一部分数量.
    constructor(string memory name, string memory symbol) ERC20(name, symbol) {
        // Mint 了 100 个Token  给 msg.sender (合约部署者) 

        // 关于精度decimals:    默认会是 18 

        // 1 token = 1 * (10 ** decimals)
        _mint(msg.sender, 100 * 10**uint(decimals()));
    }
}
  • 代币的交换合约实现: Swap

类似 Uniswap , 我们创建一个交换合约, 将一种代币交换成另外一种代币.

这是一个示例合约,TokenSwap用于将一个 ERC20 代币换成另一个。

该合约将通过调用transferFrom来交换代币.

transferFrom(address sender, address recipient, uint256 amount)

这会实现, amount 数量的代币从sender转移到recipient

为了transferFrom成功,sender必须:

  • 在余额中有至少amount数量的代币

  • 允许提取 amount 数量的代币必须先调用TokenSwapapprove 函数授权

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

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.0.0/contracts/token/ERC20/IERC20.sol";

/*
如何用 Swap 兑换 Token 代币?  

1. Alice 有 100 个代币 AliceCoin, 它是一个 ERC20 代币.
2. Bob 有 100  个代币 BobCoin, 它也是一个  ERC20 代币.
3. Alice 和 Bob 想要用 10 AliceCoin 换取 20 BobCoin.
4. Alice 或者 Bob 部署了一个 TokenSwap 合约
5. Alice 授权 TokenSwap 去提取 10 AliceCoin 代币
6. Bob 授权 TokenSwap 去提取 20  BobCoin 代币
7. Alice 或者 Bob 调用 TokenSwap.swap()
8. Alice 和 Bob 交易完成 ✅ 
*/

contract TokenSwap {
    IERC20 public token1;
    address public owner1;
    uint public amount1;
    IERC20 public token2;
    address public owner2;
    uint public amount2;

    constructor(
        address _token1,
        address _owner1,
        uint _amount1,
        address _token2,
        address _owner2,
        uint _amount2
    ) {
        token1 = IERC20(_token1);
        owner1 = _owner1;
        amount1 = _amount1;
        token2 = IERC20(_token2);
        owner2 = _owner2;
        amount2 = _amount2;
    }

    function swap() public {
        require(msg.sender == owner1 || msg.sender == owner2, "Not authorized");
        require(
            token1.allowance(owner1, address(this)) >= amount1,
            "Token 1 allowance too low"
        );
        require(
            token2.allowance(owner2, address(this)) >= amount2,
            "Token 2 allowance too low"
        );

        _safeTransferFrom(token1, owner1, owner2, amount1);
        _safeTransferFrom(token2, owner2, owner1, amount2);
    }

    function _safeTransferFrom(
        IERC20 token,
        address sender,
        address recipient,
        uint amount
    ) private {
        bool sent = token.transferFrom(sender, recipient, amount);
        require(sent, "Token transfer failed");
    }
}

More from this blog

现在谁继续赚取数百万美元?正确答案:鲸鱼和内幕钱包。

现在谁继续赚取数百万美元?正确答案:鲸鱼和内幕钱包。 因为市场完全依赖于他们的操纵, 他们在任何游戏中,拥有绝对优势。 因为Axiom等工具具备监控功能,所以他们也会经常替换钱包: 💰钱包实时监控:https://axiom.trade/@0xcii 📱钱包监控:https://debot.ai?inviteCode=174709 分享一批上周的链上顶级内幕钱包🧵👇 我花了很多时间在链上筛选这些钱包! 请关注我 @AntCaveClub,点赞并转发——确保不再...

Apr 18, 20251 min read37

这个钱包昨天一笔交易用 0.9 Eth 赚了 8.4 Eth

几乎是交易市场的一条定律: 不管新闻是真假, 它带来的影响是真的就行。 昨天,我们知道 特朗普团队发币这一消息后, 第一时间关注市场上的新币。 发现了 ETH 链上的 $DJT 代币, 当时市值仅 $450K , 而现在达到了 $ 3.3 M 。 由于信息较少, 小入了一手, 然后发公告了,估计都跌麻木了没人上车,结果今天获利 8 倍。 另一个值得 关注的信息是特朗普最大主题代币 $TRUMP 今日突然下跌 -40% 我们通过链上数据观察, 这部分游资进入了 $DJT 而这个...

Jun 18, 20241 min read359

Ton 会成为真正的独角兽,因为它拥有

TON 才是独角兽。 正确使用TON 工具能给你带来财富。 SOL / ETH 的 memcoins 交易良好,但 TON 正在超越它。 以下 5 个基本工具可帮助你获得 10-100 倍收益 1⃣️ TON 的土壤 显然,TON 上的 memcoin 越来越受欢迎,TON 市值已超过 160 亿美元。 $NOT 上线币安,其涨幅众所周知。其他大量 TON memcoin 会增值 10-100 倍。让我们学习一下用于搜寻早期 TON 山寨币的主要工具…… 2⃣️ Defilla...

Jun 5, 20241 min read109

昨晚用 1 Eth 赚了 10 Eth ! 没想到睡觉起来就这样了。

昨天睡觉前搞了 $DEW 建仓时市值 500K 附近, 现在 6M 左右了, 一晚上 10 倍。 最近确实以太坊链上出金狗,千万市值天天都有。 也主要因为我睡着了, 睡之前和朋友讲了下,建议他上车,他说他在打球🏀 推荐 $DEW 的主要原因是, 我前几天不是推了 $PEW ,推的时候市值 $2 M 附近,结果 3天一路干到了 $94 M , 大概快有 50 倍... 当时跟朋友讲让他上点车, 他在追剧,忘上车了, 我说下次一定。 他推荐我看《庆余年》,说这个好看。 昨晚看到出...

Jun 1, 20241 min read333

专注 Web3 网络赚钱模式, 区块链实践教程与交流分享

127 posts

专注 Web3 网络赚钱模式, 实践教程与交流分享 !

加入社群 | 订阅Youtube