1、ERC20简介
数字加密货币大致可以分为原生币(coin)和代币(token)两大类。前者如BTC、ETH等,拥有自己的区块链。后者如Tether、TRON、ONT等,依附于现有的区块链。市场上流通的基于以太坊的代币大都遵从ERC20协议。
ERC20的全名叫:Ethereum Request for Comments 20。最先是以太坊社区团体提出来的。大家可以把它看做是一份协议,当你想创建自己的代币时,你就必须要遵守这份协议,这样后期才会有更多的第三方应用对你发行的代币进行支持。
ERC20是一段代码,主要有6个功能,分别是名称,简写,以及可以支持的最大位数以及定义查询方法等等。从ERC20发币的开源代码可以看出,如果一旦你要发币,首先就是要确定名称,代币简称,总量,代币精确小数点后多少位等等。
在编写了一份标准的ERC20智能合约之后,第三方机构就会用事先编写好的自定义代码与你的代币合约建立通信,这样人们就可以开始交易你的代币或把它存入钱包了。
2、合约编写
pragma solidity >=0.4.22 <0.5.0;
//ERC20协议接口
contract ERC20Interface{
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);
}
/**
* @title SafeMath 安全计算,避免溢出
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
/**
* @title Ownable 权限控制
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
//这里是个事件,供前端监听
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.这是一个构造函数,在合约启动时只运行一次,将合约的地址赋给地址owner
*/
function Ownable() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner。这里就是modifier onlyOwner的修饰符,用来判定是否是合约的发布者
* 修饰器,通常用于校验函数权限
只有合约的拥有者才能执行函数
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
* 让合约拥有者修改指定新的合约拥有者,并调用事件来监听
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
contract bmtToken is ERC20Interface , Ownable{
using SafeMath for uint;
//代币名称
string public name;
//代币符号 ,比如 BTC
string public symbol;
//代币精度,比如 ETC 有18位
uint8 public decimals;
//发行总额
uint public totalSupply;
//地址 => 余额 映射关系
mapping(address => uint) balances;
//授权 地址A 授权给 地址B 多少个代币
mapping(address => mapping(address => uint)) allowed;
constructor() public {
name = "BMT Token";
symbol = "BMT";
decimals = 18;
totalSupply = 1000000000000000000;
balances[msg.sender] = totalSupply;
Transfer(address(0),msg.sender,totalSupply);
}
function totalSupply() public constant returns(uint){
return totalSupply;
}
//获取账户余额
function balanceOf(address tokenOwner) public constant returns(uint){
return balances[tokenOwner];
}
//转账给地址to
function transfer(address to, uint tokens) public returns (bool){
balances[msg.sender] = balances[msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
//触发事件
Transfer(msg.sender,to,tokens);
return true;
}
//被授权账户余额
function allowance (address tokenOwner,address spender) public constant returns(uint){
return allowed[tokenOwner][spender];
}
//授权给账户address tokens个代币
function approve(address spender,uint tokens) public returns(bool){
allowed[msg.sender][spender] = tokens;
//触发事件
Approval(msg.sender,spender,tokens);
return true;
}
//from 转账给 to
function transferFrom(address from,address to,uint tokens) public returns(bool){
allowed[from][to] = allowed[from][to].sub(tokens);
balances[from] = balances[from].sub(tokens);
balances[to] = balances[to].add(tokens);
//触发事件
Transfer(from,to,tokens);
return true;
}
//niming匿名 huigun回滚 hanshu函数
function () payable{
//hanshu函数buneng不能 zhixing执行,hui会 huigun回滚
revert();
}
//合约 与 合约 之间交互,代币 与 代币 交易
function transferAnyERC20Token(address tokenAddr,uint tokens)public onlyOwner returns(bool) {
//nenggou能够 jieshou接收接收renhe接收 shix实现ERCjiekou接口 d的 daibi代币 zhuangzhang转账
ERC20Interface(tokenAddr).transfer(msg.sender,tokens);
}
}
3、发行
待补充