基于ERC20协议的智能合约demo

初次接触加密货币圈的人可能会有些困扰。 在本文中,考虑诸如代币标准、ERC20、ERC721 等术语。 现在您可能觉得一切都很陌生,但一旦您了解了它们的作用,再理解它们的概念就会非常简单。 什么是 ERC 代币? 我们在这里用大白话讲一讲。

一、首先,币或代币:它们是什么?

先来讲一下币。 这要从比特币说起,即第一个区块链网络。 比特币旨在让人们使用其原生货币(也称为比特币或 BTC)进行全球点对点支付。 随后出现了类似的区块链,如莱特币 (LTC) 和[狗币 (DOGE),它们的用途类似。

所有这些依托于自己的区块链网络的加密货币都称为币。

然后以太坊出现,并引入了基于区块链的去中心化应用和协议的概念。 尽管以太坊也有自己的“币”,名为 ETH,且使用方式与 BTC 相同,但它的主要用途是助推

基于网络搭建的应用和协议的交易和运作。

此外,这些应用的开发者可以创建应用内货币,这类货币没有专属区块链,而是存放在以太坊中。 借助以太坊,用户还可以创建其他形式的独立数字资产,这些

数字资产能够以不可更改的方式存放在以太坊中。 这些在以太坊中创建和存放的应用内货币或数字资产就是我们所说的代币。

总而言之,拥有专属区块链的加密资产从技术上来说是一种币,而在第三方区块链上创建的所有其他资产则称为代币。

二、那什么是 ERC 代币呢?

以太坊生态系统是去中心化的,但仍需要有人来制定规则,发出升级要求,并制定标准来定义区块链上的各种可能。 为此,以太坊的大部分用户需要提交以太坊

提案 (EIP),讨论具体细节,并投票决定是否决还是开始实施提案。

现在,有几种类型的 EIP 分别对应不同类别的改进和补充。 其中一种类型是以太坊核心开发者定义的,用于提出、讨论和实施在以太坊上创建代币、智能合约、应

用程序、钱包格式等的不同技术标准。

该子类别的 EIP 称为以太坊征求意见提案,又称 ERC。 到目前为止,已经可利用多个“以太坊征求意见提案”为可在以太坊上创建的代币制定标准。 而以太坊上创建

的所有代币都必须遵循这些 ERC 制定的标准。 因此,这些代表称为 ERC 代币。

目前有三种 ERC 标准在以太坊上使用最广泛:ERC20、ERC721 或 ERC1155。 为了不让您感到困惑,这里说明一下,ERC 后面的数字只是提出这些标准的“意见征

求”序号。

但是,这些标准具体指什么呢,我们为什么需要这些标准? 让我们弄清楚这个问题。

三、了解 ERC 代币标准

3.1 ERC20:可替代的/同质化代币标准

ERC20 于 2015 年首次实施,利用该代币标准,开发者可为基于以太坊的应用程序或协议创建可替代的/同质化代币。 什么?

首先,您可以将“同质化代币”想象成任何基于区块链的常规货币。 术语“同质化”仅意味着您可以将一个单位的代币交换为任何其他一个单位的该种代币,因为它们

代表的价值相同。 在这一点上,以 UNI 或 LINK 这样的加密资产为例,即基于以太坊的协议 Uniswap或Chainlink的 ERC20 代币。 每一种此类代币都是同质化

的,因为一个 UNI 或 LINK 代币始终等于任何其他 UNI 或 LINK 代币。

这意味着您可以一比一交换上述代币。 您拥有哪个 UNI 并不重要,因为它们的基础价值始终与所有其他 UNI 代币相同。

3.2 ERC721:非同质化代币标准

随着区块链的用途越来越广泛,需要对区块链上的唯一数据进行代币化和表示。 由此便引入了 ERC721 代币标准。 利用 ERC721 标准,您可以创建不可替代/非同

质化代币,即每个代币都具有独特价值,代表可验证的唯一数字对象,不能像 ERC20 代币那样相互交换。

因此,假设您想在区块链上表示一件数字艺术品。 显然不能用 ERC20 代币来表示。 您可以改用 ERC721 标准代币来创建 NFT 艺术作品。 这个数字艺术作品的

NFT 可轻松证明该艺术作品的真实性及其所有权记录。

由于 NFT 艺术品的所有权记录和身份是不可更改的,且存储在区块链上,此举也避免了对任何艺术家原创作品的伪造。

3.3 ERC1155:多重代币标准

ERC20 和 ERC721 标准的问题在于,它们仅允许一个智能合约支持单一类型的可替代/同质化或不可替代的/非同质化代币。 因此,每次要部署新代币时,都必须编

写一个新的智能合约。 此外,上述两个标准均未提供创建半可替代/半同质化代币的方法。

由此 ERC1155 代币标准应运而生,让以太坊开发者能够使用同一标准创建同质化、半同质化和非同质化的代币。 此外,利用 ERC1155,制定一份合约即可支持多

种类型的可单独配置的代币,从而降低了代币创建过程的复杂性。 这样说有点复杂,对吗? 我们来简化一下。

假设一个开发者想开发一款 NFT 游戏,他们计划创建一种同质化的代币作为游戏中使用的货币,同时计划创建多种非同质化代币,来代表游戏中的独特资产,如

皮肤、枪支、商品等。 如果采用 ERC20 和 ERC721 标准,那么创建每一种新的资产类型时他们都必须要编写新的智能合约作为支持。 然而,借助 ERC1155,他

们只要编写一份合约即可支持他们想在游戏中拥有的所有种类的代币。

这些并不能说明某个标准比其他标准好;它们只是用途不同。

四、基于ECR20协议手动实现合约demo

pragma solidity ^0.8.0;

contract ecr20 {

    // 账户余额
    mapping (address => uint256) private _balances;

    // 代币名称
    string private _name;

    // 代币符号
    string private _symble;

    // 代币精度 默认18位
    uint8 private _decimals = 18;

    // 代币总量
    uint256 private _totalApply;

    // 代币最大总量
    uint256 private _maxApply;

    // 定义合约拥有者
    address public owner;
    // 权限
    modifier onlyOwner() {
        require(msg.sender == owner, "account is not owner");
        _;
    }

    // 构造函数
    constructor(string memory name, string memory symble, uint256 maxApply) public {
        _name = name;
        _symble = symble;
        _maxApply = maxApply;
        owner = msg.sender;
    }

    // 查询账户姓名
    function name() public view returns (string memory) {
        return _name;
    }
    // 查询代币符号
    function symble() public view returns (string memory) {
        return _symble;
    }
    // 查询代币精度
    function decimals() public view returns (uint8) {
        return _decimals;
    }
    // 查询代币总量
    function totalApply() public view returns (uint256) {
        return _totalApply;
    }
    // 查询最大总量
    function maxApply() public view returns (uint256) {
        return _maxApply;
    }
    // 查询账户余额
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }
    
    // 转账
    function transfer(address to, uint256 amount) public returns (bool) {
        // 转账发起人账号(谁调用这个函数就是谁)
        address from = msg.sender;
        // 查一下发起人钱包余额
        uint256 fromBalance = _balances[from];
        // 判断转账人余额是否大于转账金额
        require(fromBalance >= amount, "Over user balance");
        // 转账逻辑
        _balances[from] -= amount;
        _balances[to] += amount;

        return true;
    }

    // mint函数(给账户生成代币)
    function mint(address to, uint256 amount) public onlyOwner {
        require(_totalApply + amount <= _maxApply, "over _maxApply");
        _totalApply += amount;
        _balances[to] += amount;
    }

    // 改账户拥有者
    function setOwner(address _owner) public onlyOwner {
        owner = _owner;
    }


}