通過token(代幣)學習智慧合約開發,含例項demo
阿新 • • 發佈:2018-11-10
token是什麼?
關於token(代幣)是什麼,相信很多人一開始會有疑問,它和比特幣和以太幣有什麼區別呢?可以看下我的另外一篇文章介紹:https://blog.csdn.net/qq_34493908/article/details/81838954
智慧合約是什麼?
智慧合約就是執行在以太坊上的程式,是程式碼和資料(狀態)的集合。可以用智慧合約來實現代幣。
ERC20是什麼?
ERC20是一種代幣的標準,要想實現一個代幣,我們必須要有一個統一的標準才行,不然的就會很混亂。那這個標準涵蓋的內容什麼呢,如指定代幣名稱、總量、實現代幣交易函式等,只有支援了協議才能被以太坊錢包支援。大家可以看下這篇文章: https://www.jianshu.com/p/a5158fbfaeb9。
首先,我們要寫一個ERC20的介面:
pragma solidity ^0.4.20;
//ERC20標準,一種以太坊代幣的標準
contract ERC20Interface {
string public name; //返回string型別的ERC20代幣的名字
string public symbol; //返回string型別的ERC20代幣的符號,也就是代幣的簡稱,例如:SNT。
uint8 public decimals; //支援幾位小數點後幾位。如果設定為3。也就是支援0.001表示
uint public totalSupply; //發行代幣的總量
//呼叫transfer函式將自己的token轉賬給_to地址,_value為轉賬個數
function transfer(address _to, uint256 _value) returns (bool success);
//與下面approve函式搭配使用,approve批准之後,呼叫transferFrom函式來轉移token。
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) ;
//批准_spender賬戶從自己的賬戶轉移_value個token。可以分多次轉移。
function approve(address _spender, uint256 _value) returns (bool success);
//返回_spender還能提取token的個數。
function allowance(address _owner, address _spender) view returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
接著就是實現一個ERC20標準:
pragma solidity ^0.4.20;
import "./erc20interface.sol";
contract ERC20 is ERC20Interface{
mapping(address => uint256) public balanceOf;//餘額
mapping(address =>mapping(address => uint256)) allowed;
constructor(string _name,string _symbol,uint8 _decimals,uint _totalSupply) public{
name = _name; //返回string型別的ERC20代幣的名字
symbol = _symbol; //返回string型別的ERC20代幣的符號,也就是代幣的簡稱,例如:SNT。
decimals = _decimals; //支援幾位小數點後幾位。如果設定為3。也就是支援0.001表示
totalSupply = _totalSupply; //發行代幣的總量
balanceOf[msg.sender]=_totalSupply;
}
//呼叫transfer函式將自己的token轉賬給_to地址,_value為轉賬個數
function transfer(address _to, uint256 _value) public returns (bool success){
require(_to!=address(0));//檢測目標帳號不等於空帳號
require(balanceOf[msg.sender] >= _value);
require(balanceOf[_to] + _value >=balanceOf[_to]);
balanceOf[msg.sender]-=_value;
balanceOf[_to]+=_value;
emit Transfer(msg.sender,_to,_value);//觸發事件
return true;
}
//與下面approve函式搭配使用,approve批准之後,呼叫transferFrom函式來轉移token。
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){
require(_to!=address(0));
require(balanceOf[_from]>=_value);
require(balanceOf[_to]+_value>balanceOf[_to]);
require(allowed[_from][msg.sender]>_value);
balanceOf[_from]-=_value;
balanceOf[_to]+=_value;
allowed[_from][msg.sender]-=_value;
emit Transfer(_from,_to,_value);
return true;
}
//批准_spender賬戶從自己的賬戶轉移_value個token。可以分多次轉移。
function approve(address _spender, uint256 _value) public returns (bool success){
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender,_spender,_value);
return true;
}
//返回_spender還能提取token的個數。
function allowance(address _owner, address _spender) public view returns (uint256 remaining){
return allowed[_owner][_spender];
}
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
另外在真正實現一個代幣前,我們還需要一個代幣的管理者:
pragma solidity ^0.4.20;
//實現一個代幣的管理者
contract owned{
address public owner;
constructor() public{
owner=msg.sender;
}
modifier onlyOwner{
require(msg.sender==owner);
_;
}
function transferOwnerShip(address newOwner) public onlyOwner{
owner=newOwner;
}
}
最終就是一個實現可以增發、凍結、銷燬的代幣
pragma solidity ^0.4.20;
import "./erc20.sol";
import "./owned.sol";
//高階代幣繼承自前兩個合約
contract AdvanceToken is ERC20,owned {
mapping(address => bool) public frozenAccount;//宣告凍結或者解凍的帳號
event AddSupply(uint256 amount);//宣告增發事件
event FrozenFunds(address target,bool freeze);//宣告凍結或者解凍事件
event Burn(address account,uint256 values);
constructor(string _name,string _symbol,uint8 _decimals,uint _totalSupply) ERC20 ( _name,_symbol, _decimals,_totalSupply) public{
}
//代幣增發函數
function mine(address target,uint256 amount) public onlyOwner{
totalSupply+=amount;
balanceOf[target]+=amount;
emit AddSupply(amount);//觸發事件
emit Transfer(0,target,amount);
}
//凍結函式
function freezeAccount(address target,bool freeze) public onlyOwner{
frozenAccount[target]=freeze;
emit FrozenFunds(target,freeze);
}
//呼叫transfer函式將自己的token轉賬給_to地址,_value為轉賬個數
function transfer(address _to, uint256 _value) public returns (bool success){
require(!frozenAccount[msg.sender]);//判斷賬戶是否凍結
require(_to!=address(0));//檢測目標帳號不等於空帳號
require(balanceOf[msg.sender] >= _value);
require(balanceOf[_to] + _value >=balanceOf[_to]);
balanceOf[msg.sender]-=_value;
balanceOf[_to]+=_value;
emit Transfer(msg.sender,_to,_value);//觸發事件
return true;
}
//呼叫transferFrom函式來轉移token。
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){
require(!frozenAccount[msg.sender]);//判斷賬戶是否凍結
require(_to!=address(0));
require(balanceOf[_from]>=_value);
require(balanceOf[_to]+_value>balanceOf[_to]);
require(allowed[_from][msg.sender]>_value);
balanceOf[_from]-=_value;
balanceOf[_to]+=_value;
allowed[_from][msg.sender]-=_value;
emit Transfer(_from,_to,_value);
return true;
}
//銷燬函式
function burn(uint256 values) public returns(bool success){
require(balanceOf[msg.sender]>=values);
totalSupply-=values;
balanceOf[msg.sender]=values;
emit Burn(msg.sender,values);
return true;
}
}