「这是我参与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不计其数,但我们不要去炒作这些代币,要深刻理解其中的技术逻辑,掌握智能合约的关键技术。