智能合约入门系列(六) -ERC20

492 阅读3分钟

「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战

前言

 ERC20是以太坊定义的一个代币标准。 要求我们在实现代币的时候必须要遵守的协议,如指定代币名称、总量、实现代币交易函数等,只有支持了协议才能被以太坊钱包支持。ERC20 让以太坊区块链上的其他智能合约和去中心化应用之间无缝交互。一些具有部分但非所有ERC20标准功能的代币被认为是部分 ERC20兼容,这还要视其具体缺失的功能而定,但总体是它们仍然很容易与外部交互。

官方的标准如下:eips.ethereum.org/EIPS/eip-20

ERC20方法

contract ERC20Interface {

    string public constant name = "Token Name";
    string public constant symbol = "TNT";
    uint8 public constant decimals = 18;  // 18 is the most common number of decimal places

    function totalSupply() public constant returns (uint);
    function balanceOf(address tokenOwner) public constant returns (uint balance);
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
    function transfer(address to, uint tokens) public returns (bool success);
    function approve(address spender, uint tokens) public returns (bool success);
    function transferFrom(address from, address to, uint tokens) public returns (bool success);

    event Transfer(address indexed from, address indexed to, uint tokens);
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

如上是ERC20标准的函数,我们需要实现它的方法。

方法说明

1.name

这是代表代币的名称。

2.symbol

表示代币的符号,简称。

3.decimals

代币小数点位数,代币的最小单位, 18表示我们可以拥有 .0000000000000000001单位个代币。

4.totalSupply

这是发行代币总量。

5.balanceOf

这个方法可以查看对应账号的代币余额。

6.allowance

返回授权花费的代币数。即_spender可以从账户_owner中转出token的剩余数量

7.transfer

实现代币转账交易,用于给用户发送代币(从我们的账户里)。

交易代币 从消息发送者账户中往_to账户转数量为_value的token, 从代币合约的调用者地址上转移 _value的数量token到的地址 _to 【注意:并且必须触发Transfer事件】

8.approve

批准_spender能从合约调用账户中转出数量为_value的token。

9.transferFrom

两个地址转账 从账户_from中往账户_to转数量为_value的token,与approve方法配合使用 从地址 _from发送数量为 _value的token到地址 _to 【注意:并且必须触发Transfer事件】 transferFrom方法用于允许合约代理某人转移token。条件是from账户必须经过了approve。

10.event Transfer

代币转移时触发

11.event Approval

代币授权出去时触发。

下面看一个完整的代币合约

//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "./erc20.sol";
contract ERC20 is ERC20Interface{   
 string public _name = "JZ";  
  string public _symbol = "JZT";  
  uint8 public _decimals = 18;  // 18 是建议的默认值   
 uint256 public _totalSupply;       
 mapping (address => uint256) public _balanceOf;    
mapping (address => mapping (address => uint256)) _allowance;     
       event Transfer(address indexed _from, address indexed _to, uint256 _value);   
 event Approval(address indexed _owner, address indexed _spender, uint256 _value);  
        
  function name() public view virtual override returns (string memory){       
 return _name;  
  }   
 function symbol() public view virtual override returns (string memory){     
   return _symbol;  
  }    
function decimals() public view virtual override returns (uint8 ){      
  return _decimals;   
 }   
 function totalSupply() public view virtual override returns (uint256 ){    
    return _totalSupply;  
  }  
  function balanceOf(address _owner) public  view virtual override returns (uint256 balance){    
  
  balance = _balanceOf[_owner];  
  }   
 function _transfer(address _from, address _to, uint256 _value) internal virtual {      
  require(_from != address(0));       
 require(_to != address(0));      
  require(_balanceOf[_from] >= _value);    
    _balanceOf[msg.sender]-=_value; 
       _balanceOf[_to]+=_value;     
  emit Transfer(_from, _to, _value);  
  }  
  function _approve(address _owner, address _spender, uint256 _value) internal virtual {   
     require(_owner != address(0));       
 require(_spender != address(0));      
   _allowance[_owner][_spender] = _value;     
   emit Approval(_owner, _spender, _value);  
  }   
 function transfer(address _to, uint256 _value) public virtual override returns (bool success){    
    _transfer(msg.sender, _to, _value);       
 success = true;  
  }   
 function transferFrom(address _from, address _to, uint256 _value) public virtual override returns (bool success){      
  _transfer(_from, _to, _value);    
    uint256 allowanceNum = _allowance[_from][_to];       
 require(allowanceNum >= _value);  
      _approve(_from, _to, allowanceNum - _value);    
    success = true;   
 }   
 function approve(address _spender, uint256 _value) public virtual override returns (bool success){      
  _approve(msg.sender, _spender, _value);      
  success = true;   
 }    
function allowance(address _owner, address _spender) public view virtual override returns (uint256 remaining){    
    return _allowance[_owner][_spender];  
  }   
 function _mint(address _account, uint256 _value) internal virtual{     
   require(_account != address(0));      
  _totalSupply += _value;     
   _balanceOf[_account] += _value;     
   emit Transfer(address(0), _account, _value);  
  }  
  }

总结

以太坊的ERC20标准成为了公认的一种标准,现在发行在以太主网上的erc20不计其数,但我们不要去炒作这些代币,要深刻理解其中的技术逻辑,掌握智能合约的关键技术。