以太坊標準令牌系列之同質化令牌ERC20

0x00 寫在前面

衆所周知,以太坊在現階段最大的應用就是令牌發行,而在以太坊中有不少類型的令牌,最著名的當屬ERC20了,可是對於其餘幾種令牌類型,可能還有一些朋友不知道,因此最近規劃了一個系列,就是以太坊標準令牌系列。javascript

目前市面上,凡是基於以太坊的令牌,在交易所上線交易的均是ERC20令牌,那麼今天咱們就來聊聊ERC20令牌的標準方案吧。java

0x01 ERC20標準制定動機

在基於以太坊發行令牌時,若是各個令牌發行方都使用自有標準去發行令牌,那對於錢包開發者以及交易所對接成本是極其高昂了,由於他們須要爲每一種令牌去獨立進行對接,爲了下降錢包開發者以及交易所的對接成本,以太坊社區制定了一個關於令牌的發行標準。編程

該標準中主要包含了,令牌的轉移,地址餘額的獲取等方法。app

0x02 ERC20標準規範

一個令牌的合約,通常須要令牌的發行量,每一個地址的餘額,令牌的轉移等方法, 而ERC20標準就是將這些最經常使用又是必不可少的方法,對此進行標準化,方便開發者進行令牌合約的開發,也方便錢包開發者以及交易所對接成本降到最低。函數

其中,定義了三類,方法、屬性、事件。post

下面介紹這些標準方法:ui

A. 方法(Method)

一、totalSupply:令牌總量

函數原型
function totalSupply() constant returns (uint256 totalSupply)

方法 該方法用於獲取令牌總髮行量spa

二、balanceOf:獲取餘額
函數原型
function balanceOf(address _owner) constant returns (uint256 balance)

方法 該方法用於獲取地址 _owner 的令牌餘額日誌

三、transfer:轉帳

函數原型
function transfer(address _to, uint256 _value) returns (bool success)

方法 該方法用於將調用令牌合約的地址中的_value個令牌轉給_to 地址code

四、transferFrom:轉帳

函數原型
function transferFrom(address _from, address _to, uint256 _value) returns (bool success)

方法 該方法用於從_from 地址中發送_value 個令牌給_to地址。

當你但願可以使用其餘智能合約控制你的令牌轉移,則可使用transferFrom方法,而使用transferFrom方法有一個前提條件,那就是須要調用者須要獲得 _from 地址的受權,才能夠進行令牌轉移的操做。而如何進行受權,咱們接下來會介紹。

五、approve:受權

函數原型
function approve(address _spender, uint256 _value) returns (bool success)

方法 容許 _spender 地址從你的帳戶中轉移 _value 個令牌到任何地方。

當你設置了一個 _value 以後,_spender 地址能夠分任何屢次將令牌進行轉移,直至_value爲0.

六、allowance:獲取被受權令牌餘額

函數原型
function allowance(address _owner, address _spender) constant returns (uint256 remaining)

方法 獲取 _owner 地址受權給 _spender 地址能夠轉移的令牌的餘額。

B. 事件(Event)

事件是EVM內置的日誌功能,並且在DAPP中,咱們能夠經過JS來監聽事件的回調。在ERC-20令牌中,定義瞭如下事件:

一、Transfer:轉移令牌
事件定義
event Transfer(address indexed _from, address indexed _to, uint256 _value)

當進行令牌轉移時,須要觸發調用該事件。其中記錄了令牌發送者_from,令牌接受者_to ,令牌發送量_value.

二、Approval:受權事件
事件定義
event Approval(address indexed _owner, address indexed _spender, uint256 _value)

當進行受權時,須要觸發調用該事件,其中記錄了受權者_owner,被受權者_spender,受權令牌量_value

0x03 ERC20令牌接口

經過以上的標準,咱們能夠了解到一個遵照ERC20令牌標準的令牌合約須要實現的方法,如下是經過規範實現的一個ERC20令牌的接口。

contract EIP20Interface {
    
    ///////////////////////////// 方法 ///////////////////////////////////
    
      // 獲取令牌發行量
    // 注意:constant的修飾符是提示該方法中不能進行變量的修改。
    //      但編譯器不會強制校驗。
    // @return uint256 totalSupply 總髮行量
    function totalSupply() constant returns (uint256 totalSupply)

       // 獲取指定地址
    // @param address _owner 想要獲取的地址
    // @return uint256 balance 令牌餘額
    function balanceOf(address _owner) public view returns (uint256 balance);

    // 從`msg.sender`中發送`_value`個令牌給`_to` 
    // @param address _to 接收令牌的地址
    // @param uint256 _value 發送的令牌數量
    // @return bool success 發送令牌成功狀態
    function transfer(address _to, uint256 _value) public returns (bool success);

    // 從`_from`地址發送`_value`令牌到`_to`地址
    // 須要知足條件,須要被`_from`地址受權給`msg.sender`
    // @param address _from 發送者地址
    // @param address _to 接收者地址
    // @param uint256 _value 發送的令牌數量
    // @return bool success 發送令牌成功狀態
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);

    // `msg.sender`受權`_spender`地址能夠任意轉移`_value`數量的令牌
    // @param address _spender 被受權發送令牌的地址
    // @param uint256 _value 受權發送令牌的數量
    // @return bool success 受權成功狀態
    function approve(address _spender, uint256 _value) public returns (bool success);

    /// @param _owner The address of the account owning tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens allowed to spent
    // 獲取被受權限額
    // @param address _owner 令牌全部者的帳戶
    // @param address _spender 令牌被受權者帳戶
    // @return uint256 remaining 剩餘可發送的令牌數量
    function allowance(address _owner, address _spender) public view returns (uint256 remaining);
    
    ///////////////////////////// 事件 ///////////////////////////////////
    // 令牌轉移事件 當發生令牌的轉移時,須要調用該事件
    event Transfer(address indexed _from, address indexed _to, uint256 _value); 
    // 受權轉移事件 當進行受權時,須要觸發該事件
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

0x04 ERC20代碼示例

在標準的基礎上,有不少代碼的實現方法,好比有的在代碼中實現空投,有的在實現鎖定,有的實現挖礦等等,可是最常規的實現已經有了官方的實現代碼,也有不少組織實現了一些範例,若是沒有定製化的地方,徹底能夠直接採用這些代碼去建立ERC20令牌。

示例代碼:

pragma solidity ^0.4.18;

contract ERC20 {

    // 定義一個mapping 存儲各個地址的令牌
    mapping (address => uint256) public balances;
    // 定義一個mapping 存儲受權詳情
    mapping (address => mapping (address => uint256)) public allowed;
    
    // 如下參數非必須,可是儘可能添加,大多數錢包會經過此獲取相關信息

    // 令牌發行總量
    uint256 public totalSupply;

    // 令牌名稱,如 OmiseGO
    string public name;      
    // 支持的小數位數
    // 由於在EVM中對浮點數的支持不好,在令牌的建立中直接採用整數
    // 而後經過該字段進行小數的處理
    uint8 public decimals;                
    // 令牌簡稱,如 OMG
    string public symbol;              

    // 令牌合約的構造函數
    // 在solidity中,和合約名稱一致的方法爲構造函數,在第一次建立合約時,僅執行一次。
    function ERC20(
        uint256 _totalSupply,    // 令牌建立總量
        string _name,        // 令牌名稱
        uint8 _decimals,    // 支持小數位數
        string _symbol        // 令牌簡稱
    ) public {
        // 給建立者帳戶初始化令牌
        balances[msg.sender] = _totalSupply;               
        // 設置令牌發行量
        totalSupply = _totalSupply;                        
        // 設置令牌名稱
        name = _name;                                   
        // 設置令牌支持小數位數
        decimals = _decimals;                            
        // 設置令牌簡稱
        symbol = _symbol;                               
    }

    /**
     * 獲取令牌總髮行量
     * @return uint256 totalSupply 發行總量
     */
    function totalSupply() constant returns (uint256 totalSupply) {
        return totalSupply;
    }

    /**
     * 轉移令牌
     * @param address _to 令牌接收者地址       
     * @param uint256 _value 發送令牌數量
     * @return bool success 發送成功狀態
     */
    function transfer(address _to, uint256 _value) public returns (bool success) {
        // 判斷髮送者餘額是否充足
        require(balances[msg.sender] >= _value);
        // 從發送者餘額中減去`_value`數量的令牌
        balances[msg.sender] -= _value;
        // 給接收者帳戶中添加`_value`數量的令牌
        balances[_to] += _value;
        // 記錄令牌轉移的事件
        Transfer(msg.sender, _to, _value);
        return true;
    }

    /**
     * 轉移令牌(受權)
     * @param address _from 令牌發送者地址
     * @param address _to 令牌接收者地址
     * @param uint256 _value 令牌發送數量
     * @return bool success 方法執行狀態
     */
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {

        // 其中`msg.sender`是合約方法調用者的地址

        // 獲取`_from`地址受權給`msg.sender`地址的可轉移令牌餘額
        uint256 allowance = allowed[_from][msg.sender];
        
        // 判斷`_from`地址餘額是否充足以及受權轉移令牌是否充足
        require(balances[_from] >= _value && allowance >= _value);
        
        // 從`_from`地址減去`_value`數量的令牌
        balances[_from] -= _value;
        
        // 從受權餘額中減去`_value`數量的令牌
        allowed[_from][msg.sender] -= _value;

        // 給`_to`地址添加`_value`數量的令牌
        balances[_to] += _value;

        // 記錄轉移令牌的事件
        Transfer(_from, _to, _value);
        return true;
    }

    /**
     * 獲取`_owner`地址的令牌餘額
     * @param address _owner 要獲取餘額的地址
     * @return uint256 balance 返回`_owner`地址的餘額
     */
    function balanceOf(address _owner) public view returns (uint256 balance) {
        return balances[_owner];
    }   

    /**
     * 受權令牌轉移方法
     * @param address _spender 被受權地址
     * @param uint256 _value 受權可轉移的數量
     * @return bool success 方法執行狀態
     */
    function approve(address _spender, uint256 _value) public returns (bool success) {
        // `msg.sender`受權`_spender`地址轉移`_value`數量的令牌
        allowed[msg.sender][_spender] = _value;

        // 記錄受權事件
        Approval(msg.sender, _spender, _value);
        return true;
    }

    /**
     * 獲取被受權的令牌餘額
     * @param address _owner 受權地址
     * @param address _spender 被受權地址        
     * @return uint256 remaining 可轉移的令牌餘額
     */
    function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }   
}

0x05 寫在後面

大多數在交易所交易的令牌的合約代碼就這麼簡單,其實每個方法拆分開來都是最簡單的編程代碼,而核心的處理都被EVM進行了封裝,以太坊在令牌發行方面確實極大的解放了人類,簡單幾十行代碼就能夠發行一個令牌。ERC20令牌又被成爲同質化令牌,就是每一個令牌都是一致的,沒法區分,而市場上如今冒出了不少以太貓,以太狗的遊戲,而這裏面也是使用以太坊的令牌來實現的,可是他們選擇的不是ERC20令牌,而是被成爲非同質化的令牌,被稱爲ERC721令牌。

下期,咱們一塊兒來聊非同質化令牌ERC721。

喜歡,不要說話,掃我~

qrcode_for_gh_0f12fe5ef5fd_258.jpg

相關文章
相關標籤/搜索