1. 程式人生 > >通過token(代幣)學習智慧合約開發,含例項demo

通過token(代幣)學習智慧合約開發,含例項demo

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;
  }

}