1、什么是ERC20协议?
ERC20是一个基于以太坊(Etherenum)代币(Token)的接口标准(协议)。所有符合ERC20标准的代币都能立即兼容以太坊钱包。
ERC20标准是在2015年11月份推出的,使用这种规则的代币,表现出一种通用的和可预测的方式。
ERC20代币是以太坊代币的子集,这些所有代币通过ERC20标准能够让以太坊区块链上的其他职能合约和去中心化应用之间无缝交互。
ERC20标准还有待完善。其中一个障碍:将代币(Token)直接发送到智能合同将导致资金损失。这也是ERC223标准诞生的原因。
2、ERC20协议的标准
Functions
2.1、name 代币的名字
function name() view returns (string name)
2.2、symbol 代币的符号(简称)
function symbol() constant returns (string symbol)
2.3、decimals 代币支持小数点后几位
function decimals() constant returns (unit decimals)
2.4、totalSupply 代币发行总量
function totalSupply() constant returns (unit totalSupply)
2.5、balanceOf 获取该地址代币余额
function balanceOf(address _owner) constant returns (unit balance)
2.6、transfer 将自己的token转账给_to地址,_value 为转账个数
function transfer(address _to,unit256 _value) returns(bool success)
2.7、approve 同意_spender账户从自己的账户转移_value个Token。可以分次转移
function approve(address _spender,unit256 _value) returns (bool success)
2.8、transferFrom 与approve配合使用,approve同意之后,调用该函数来转移Token
function transferFrom(address _from,address _to,unit _value) returns (bool success)
2.9、allowance 返回_spender还能提取token的个数
function allowance(address _owner,address _spender)constant returns(unit256 remaining)
Events
2.10、Transfer 当成功转移Token时,一定要出发Transfer事件
event Transfer(address indexd _from,address indexd _to,unit256 _value)
2.11、Approval 当调用approval函数成功时,一定要触发Approval事件
event Approval(address indexd _owner,address indexd _spender,unit _value)
3、ERC20协议的实例
/*
Implements EIP20 token standard: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
.*/
pragma solidity ^0.4.21;
import "./EIP20Interface.sol";
contract EIP20 is EIP20Interface {
uint256 constant private MAX_UINT256 = 2**256 - 1;
mapping (address => uint256) public balances;
mapping (address => mapping (address => uint256)) public allowed;
/*
NOTE:
The following variables are OPTIONAL vanities. One does not have to include them.
They allow one to customise the token contract & in no way influences the core functionality.
Some wallets/interfaces might not even bother to look at this information.
*/
string public name; //fancy name: eg Simon Bucks
uint8 public decimals; //How many decimals to show.
string public symbol; //An identifier: eg SBX
function EIP20(
uint256 _initialAmount,
string _tokenName,
uint8 _decimalUnits,
string _tokenSymbol
) public {
balances[msg.sender] = _initialAmount; // Give the creator all initial tokens
totalSupply = _initialAmount; // Update total supply
name = _tokenName; // Set the name for display purposes
decimals = _decimalUnits; // Amount of decimals for display purposes
symbol = _tokenSymbol; // Set the symbol for display purposes
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balances[msg.sender] >= _value);
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value); //solhint-disable-line indent, no-unused-vars
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
uint256 allowance = allowed[_from][msg.sender];
require(balances[_from] >= _value && allowance >= _value);
balances[_to] += _value;
balances[_from] -= _value;
if (allowance < MAX_UINT256) {
allowed[_from][msg.sender] -= _value;
}
emit Transfer(_from, _to, _value); //solhint-disable-line indent, no-unused-vars
return true;
}
function balanceOf(address _owner) public view returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value); //solhint-disable-line indent, no-unused-vars
return true;
}
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
return allowed[_owner][_spender];
}
}