关于以太坊ERC-20通证智能合约协议

关于以太坊ERC-20通证智能合约协议,第1张

文章目录 ERC-20协议是什么意思?取值函数totalSupplybalanceOfallowance *** 作函数transferapprovetransferFrom 事件TransferApproval ERC-20 通证的基本实现


ERC-20协议是什么意思?

ERC代表“Etuereum Request for Comment”,以太坊社区为了创建一个以太坊平台的标准,开发人员提交了一个以太坊改进方案(EIP),改进方案中包括协议规范和合约标准。最终确定的EIP为以太坊开发者提供了一套可实施的标准。这使得智能合约可以遵循这些通用的接口标准来构建。可以在这里检索到所有EIP提案。

而ERC-20是以太坊上最重要的智能合约标准之一。它已经成为基于以太坊公链上用于发行可替换通证,所使用智能合约的技术标准。ERC-20 定义了所有可替换的以太坊通证都应该遵守的通用规则列表。 这简化了开发者的任务,开发者知道只要通证遵循标准中的规则,每次发布新的通证时就不需要重新实现每个新项目。

知识点:什么是可替换的以太坊通证,还有不可替换的以太坊通证吗?
可替换的以太坊通证是表示通证与通证之间是完全一样的,可以被替换的,通常遵循ERC-20标准。比如A钱包中的一个ERC-20通证和B钱包中的一个相同合约地址的ERC-20通证,在区块链上看来完全一致没有什么不同,可以被相互替换。
不可替换的以太坊通证又叫非同质化通证(Non-Fungible Token)缩写为NFT,就算AB两个钱包中存在合约地址相同的两个通证,它们也存在着不一致的属性值,它们是不一样的。所以在区块链上看来是不可被相互替换的。这样的通证通常遵循ERC-721标准。

这里有段 ERC-20 接口代码,它定义了遵循 ERC-20 标准通证所必须实现的函数:

pragma solidity ^0.8.0;

interface IERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function transfer(address to, uint256 amount) external returns (bool);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

下面说明一下这些函数的用途


取值函数 totalSupply

这个函数返回存在的通证数量,展示了目前该通证的流通总量,可以被所有函数调取。该函数是一个取值函数,不会修改合约的状态。重点:Solidity 中没有浮点数。 因此,大多数通证都会采用 18 位小数,并且会返回总供应量和其他结果,如下所示:1 个通证 = 100000000000000000。 这需要在处理通证数量时格外注意,不过并不是每个通证都有 18 位小数。

function totalSupply() external view returns (uint256);
balanceOf

这个函数返回某地址拥有的通证数量(account)。 该函数同样是一个取值函数,不会修改合约的状态。

function balanceOf(address account) external view returns (uint256);
allowance

此函数被用来查看owner给spender的通证额度。此函数是一个取值函数,不会修改合约的状态,并且默认应返回 0。

function allowance(address owner, address spender)
        external
        view
        returns (uint256);

*** 作函数 transfer

将一定数量(amount)的通证从函数调用者地址(msg.sender)移动到接收者(to)地址。此函数发出稍后定义的Transfer事件。 如果可进行转账,它将返回 true,转账 *** 作需要消耗gas。

function transfer(address to, uint256 amount) external returns (bool);
approve

函数调用方(msg.sender)可以调用这个函数授权spender代表它使用amount数量的通证,即设置允许spender从函数调用方(msg.sender)余额转账的allowance的数额。 此函数发出 Approval 事件。 此函数返回是否成功设置了余量。

function approve(address spender, uint256 amount) external returns (bool);
transferFrom

使用余量机制将通证的amount从from移动到to。 然后从调用者的余量中扣除该数额。 此函数发出Transfer事件。

function transferFrom(
    address from,
    address to,
    uint256 amount
) external returns (bool);

事件 Transfer

将通证的数量value从from地址发送到to地址时会发出此事件,比如在调用 transfer 或 transferFrom 函数时。

event Transfer(address indexed from, address indexed to, uint256 value);

在铸造新的通证情况下,转账通常是 from 0x00…0000 地址,而在销毁通证的情况下,转账是 to 0x00…0000。

Approval

当owner批准要由spender使用的通证数量(value)时,将发出此事件。比如在调用 approve 函数时。

event Approval(
    address indexed owner,
    address indexed spender,
    uint256 value
);

ERC-20 通证的基本实现

下面是 ERC-20 通证的最简单代码:

pragma solidity ^0.8.0;

interface IERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function transfer(address to, uint256 amount) external returns (bool);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

contract ERC20Basic is IERC20 {
    string public constant name = "ERC20Basic";
    string public constant symbol = "ERC";
    uint8 public constant decimals = 18;

    mapping(address => uint256) balances;

    mapping(address => mapping(address => uint256)) allowed;

    uint256 totalSupply_ = 10 ether;

    constructor() {
        balances[msg.sender] = totalSupply_;
    }

    function totalSupply() public view override returns (uint256) {
        return totalSupply_;
    }

    function balanceOf(address tokenOwner)
        public
        view
        override
        returns (uint256)
    {
        return balances[tokenOwner];
    }

    function transfer(address receiver, uint256 numTokens)
        public
        override
        returns (bool)
    {
        require(numTokens <= balances[msg.sender]);
        balances[msg.sender] = balances[msg.sender] - numTokens;
        balances[receiver] = balances[receiver] + numTokens;
        emit Transfer(msg.sender, receiver, numTokens);
        return true;
    }

    function approve(address delegate, uint256 numTokens)
        public
        override
        returns (bool)
    {
        allowed[msg.sender][delegate] = numTokens;
        emit Approval(msg.sender, delegate, numTokens);
        return true;
    }

    function allowance(address owner, address delegate)
        public
        view
        override
        returns (uint256)
    {
        return allowed[owner][delegate];
    }

    function transferFrom(
        address owner,
        address buyer,
        uint256 numTokens
    ) public override returns (bool) {
        require(numTokens <= balances[owner]);
        require(numTokens <= allowed[owner][msg.sender]);

        balances[owner] = balances[owner] - numTokens;
        allowed[owner][msg.sender] = allowed[owner][msg.sender] - numTokens;
        balances[buyer] = balances[buyer] + numTokens;
        emit Transfer(owner, buyer, numTokens);
        return true;
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/2992199.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-23
下一篇 2022-09-23

发表评论

登录后才能评论

评论列表(0条)

保存