ERC系列協議標准


ERC系列協議標准

(一)概述

  在以太坊中,發布智能合約是自由的。但是,很多第三方想要做的事情可能有所類似,故延伸出來了許多基於以太坊的ERC系列協議;

 

  基於以太坊的區塊鏈平台的數字資產分為原生令牌(硬幣)和代幣(令牌)兩大類,原生的自然就是以太坊(ETH),令牌是通過智能合約創設的數字資產。代幣則是按ERC創設協議分類,主流類別有ERC20代幣,ERC223代幣,ERC721代幣,另外還有一些小眾類別,包括ERC621,ERC721和ERC827等。

 

  ERC代表“Etuereum征求意見”,這是Ethereum版的意見征求稿(RFC),ERC是由以太坊開發者為以太坊社區編寫,ERC后面的數字是議案的編號。當開發人員提交了一個以太坊改進方案(EIP),該方案一旦EIP被委員會批准並最終確定后,一個新的以太坊開發標准就形成了,它包括協議規范和合約標准;【注:好多新人都不知道這個.ERC = 以太坊請求評論,你要看EIP這個項目,應該去看問題.ERC20,就是問題#20,ERC721,就是問題#721。並不是所有的ERC都是標准,最終被采納的問題才會被收進EIP ; EIP的readme里邊有目前的狀態網站鏈接https://eips.ethereum.org】具體表現可以用抽象合約表現出來【注意:ERC並不是指某些特定的合約,而是指合約應該符合某些規范;根據具備某些特征歸類目前有ERC20,ERC223,ERC664,ERC667,ERC721,ERC875,ERC1155及ERC156等等合約協議規

 

(二)例子

1.ERC20

;下面先從最常用的ERC20鑄幣合約標准開始說,以下為一個標准的ERC20的解析:

pragma solidity ^0.4.16;

 

/**

ERC20標准

 */

contract ERC20 {

 

    /**

    代幣的名字,例如"Gavin token"

     */

    function name() constant public returns (string name);

    

    /**

    代幣的簡稱,例如:GAVC

    也是我們一般在代幣交易所看到的名字

     */

    function symbol() public constant returns (string symbol);

    

    /**

    代幣的最小分割量

    token使用的小數點后幾位。比如如果設置為3,就是支持0.001表示

     */

    function decimals() public constant returns (uint8 decimals);

    

    /**

    token的總量

     */

    function totalSupply() public  constant returns (uint totalSupply);

 

    /**

    【余額】

    返回某個地址(賬戶)的賬戶余額

    */

    function balanceOf(address _owner) public constant returns (uint balance);

 

    /**

    【轉賬】

    交易代幣

    從消息發送者賬戶中往_to賬戶轉數量為_value的token

    從代幣合約的調用者地址上轉移 _value的數量token到的地址 _to,並且必須觸發Transfer事件

     */

    function transfer(address _to, uint _value) public returns (bool success);

    

    /**

    【替某人個別人轉賬】

    從賬戶_from中往賬戶_to轉數量為_value的token,與approve方法配合使用

    從地址 _from發送數量為 _value的token到地址 _to,必須觸發Transfer事件。

    transferFrom方法用於允許合約代理某人轉移token。條件是from賬戶必須經過了approve。這個后面會舉例說明

     */

    function transferFrom(address _from, address _to, uint _value) public returns (bool success);

    

    /**

    【允許量值】

    限定_spender能從合約調用賬戶中轉出數量為_value的token

     */

    function approve(address _spender, uint _value) public returns (bool success);

    

    /**

    【限額】

    獲取賬戶_spender可以從賬戶_owner中轉出token的數量

     */

    function allowance(address _owner, address _spender) public constant returns (uint remaining);

      

    /**

    發生轉賬時必須要觸發的事件

    一般位於 transfer 和 transferFrom 函數中

     */

    event Transfer(address indexed _from, address indexed _to, uint _value);

    

    /**

    當函數approve(address _spender, uint256 _value)成功執行時必須觸發的事件

     */

    event Approval(address indexed _owner, address indexed _spender, uint _value);

}

 

上述就是ERC20 標准接口總共分為三大類: 常量、功能函數及事件

【常量】

<1> name: 代幣名稱,就是一串指定的字符串,如: "GavinNetToken"

<2> symbol: 代幣的代號,由3-4個大寫字母組成, 如: "GVTC"

<3> decimals: 小數點后幾位,表示該代幣支持最小的小數位是多少,默認為18 (ETH也是18,之所以需要有小數位字段是因為EVM 不支持小數點運算,需要在做計算的時候先轉成整型,最后根據小數位把運算結果轉換會對應的小數位)

 

【功能函數】

<4> totalSupply(): 總供應量;表示該代幣的總發行量 [后期並沒有承諾不會被更改]

<5> balanceOf(address _owner): 查詢余額;根據賬戶地址查詢該地址的余額,為無符號整數常量

<6> transfer(address _to, uint _value): 轉賬;表示合約的調用者 轉移_value 數量的token至 _to 目標賬戶地址

<7> transferFrom(address _from, address _to, uint _value): 替別人轉賬;合約調用者代替_from給_to轉賬 _value數目,【該方法需要有approve()方法的先決條件,即是說 需要_from 先用approve() 給當前合約的調用者 設置課允許當前合約調用者 代替自己(即: _from)給_to轉賬_value數目】

<8> approve(address _spender, uint _value): 給某人賦予多少轉賬數目權限;當前合約調用者給予_spender賬戶有替代自己給別人轉賬 總額為_value數目 【注意,這個方法會對一個全局的 map[最終花錢者(approve()方法的調用者)][替代自己拿着自己的錢去花者] 進行設置,后續transferFrom函數每次轉賬后都需要更新該Map中記載的被給予轉賬的余額;allowance()方法會查詢這個map中的值】

<9> allowance(address _owner, address _spender): 查詢限額的數目;查詢_spender還可以從_owner拿多少數目去花銷【底層讀取的是 approve()方法中設置的那個全局的map的值】

 

【事件】

<10> event Transfer : 每次調用 function transfer時最末尾都需要調用的事件,用於捕獲交易的日志

<11> event Approval : 每次調用 function approve時最末尾都需要調用的事件,用於捕獲給予第三方代替自己做交易事件的日志

 

至此ERC20標准的各項方法說明已經寫完;下面我們來看看ERC223標准:

各位幣圈大佬都知道,現有的 ETH 代幣基本上都基於 ERC20 標准實現,而 ERC20 存在某些嚴重問題【ERC-20標准還有待完善。其中一個障礙是,將令牌直接發送給令牌的智能合同將導致資金損失】

 

根據 ERC20 標准,交易(transaction)可以有兩種處理方式:通過transfer函數和通過approve+transferFrom,

對於開發來說,事件處理(Event Handling)是一個標准性的操作,我們所說的交易也可以被當做一種事件進行考慮。

但是很遺憾,在 ERC20 標准中,缺乏事件處理機制,也就是說,當交易發生的時候,收款人並不會得知這一消息。

 

ERC20 標准中,我們要求用戶向合約發送代幣的時候,必須使用approve+transferFrom模式進行代幣轉賬,與此同時,如果收件人是一個賬戶地址,就必須使用transfer函數完成交易。如果用戶搞錯了,這些代幣就會由於合約無法識別交易而被困在合約中。而合約沒有提供一個可以把這些困住的代幣提取出來的方法。

 

到目前為止,大概有 $3,000,000 的損失已經發生了;

 

2.ERC223

ERC223 是 ERC20 的一個升級版本。ERC223 標准提供了更安全的方法用於完成交易。

ERC223 標准中,交易發起方無需關注接收方到底是合約還是錢包地址,使代幣交易更接近 ETH 交易。

相對比 ERC20 標准,ERC223 通過全新的transfer函數,自動回滾向不支持代幣的合約發送代幣的行為。

它的實現方法是定義一個接收器(receiver),接受方合約必須通過它來正確地處理收到的代幣,否則就會有異常拋出。

 

就好像你在發送 ETH 到一個沒有payable關鍵字的合約一樣;其實就是 【它與之前的ERC20相比,該標准更注重保護合約本身和防止您的數字代幣丟失。作為ERC20的升級方案,該標准有不允許代幣轉到不支持代幣接收和處理的合約中的功能;ERC223標准允許用戶發送代幣到錢包或合同地址,從而消除了丟失代幣的危險性。同時ERC223中的轉讓合同功能讓其合同的gas消耗比ERC20少。簡而言之,ERC223更側重於安全,被譽為取代ERC20的標准】,下面我們先看看具體的ERC223標准 首先我們需要有2個*.sol文件;先看看

ERC223_Interface.sol

文件的內容

contract ERC223 {

    uint public totalSupply;

    

    /**

    代幣名稱 【同ERC20】

     */

    function name() public constant returns (string _name);

    /**

    代幣的標識符 【同ERC20】

     */

    function symbol() public constant returns (string _symbol);

    /**

    小數點后幾位 【同ERC20】

     */

    function decimals() public constant returns (uint8 _decimals);

    /**

    代幣總發行量 【同ERC20】

    */

    function totalSupply() public constant returns (uint256 _supply);

    /**

    查詢某地址余額 【同ERC20】

     */

    function balanceOf(address who) public constant returns (uint);

 

    /**

    轉賬給 某個外部賬戶 【同ERC20】

     */

    function transfer(address to, uint value) public returns (bool ok);

    /**

    轉賬給合約  該合約必須是實現了 名為: tokenFallback的函數

    data可以附加到這個令牌交易中,它將永遠保持在塊狀(需要更多的gas)。 _data可以是空的

     */

    function transfer(address to, uint value, bytes data) public returns (bool ok);

    /**

    重載 轉賬給合約

     */

    function transfer(address to, uint value, bytes data, string custom_fallback) public returns (bool ok);

    event Transfer(address indexed from, address indexed to, uint value, bytes indexed data);

}

另外

Receiver_Interface.sol

文件的內容為:

pragma solidity ^0.4.16;

/* * Contract that is working with ERC223 tokens */

contract ContractReceiver {

    struct TKN {

        address sender; //調用合約的人

        uint value;

        bytes data;

        bytes4 sig; //簽名

    }

 

    /**

    該函數表明了當調用了 transfer交易函數由A(可以使任何賬戶) 向合約B交易token時時,函數中的邏輯必須是

     _from是令牌發送者,_value是傳入令牌的數量,

    _data是附加的數據,類似於Ether事務中的數據。 適用於以太交易的回退功能,並且不返回任何內容。

    【注意】: 過濾哪些令牌(通過token合約的賬戶地址)發送可以被發送很重要。

    令牌發送者(誰發起了代幣交易的人)將_from傳入tokenFallback函數內。

    【重要】: 這個函數必須命名為tokenFallback,並使用參數地址uint256,字節來匹配函數簽名0xc0ee0b8a

     */

    function tokenFallback(address _from, uint _value, bytes _data) public {

        TKN memory tkn;

        tkn.sender = _from;

        tkn.value = _value;

        tkn.data = _data;

        uint32 u = uint32(_data[3]) + (uint32(_data[2]) << 8) + (uint32(_data[1]) << 16) + (uint32(_data[0]) << 24);

        tkn.sig = bytes4(u);

        /* tkn變量是Ether交易的msg變量的模擬 * tkn.sender是發起這個令牌交易的人(類似於msg.sender* tkn.value發送的令牌數(msg.value的類比) * tkn.data是令牌交易的數據(類似於msg.data* tkn.sig4字節的功能簽名  */

    }

}

【注意:】將在接收方合約中調用的token備用功能的函數必須命名為tokenFallback,並使用參數address, uint256,bytes。 此函數必須具有0xc0ee0b8a簽名[bytes4(keccak256('tonken(address,uint256,bytes)')) == c0ee0b8a ??]

然后,當我們需要來說一說怎么用這兩個文件【這些代碼都是網上抄的,原作者估計也是翻譯的 注釋寫的有些不對】下面演示一個ERC223的token代幣合約示例

ERC223_Token.sol

文件內容:

pragma solidity ^0.4.16;

 

import "./Receiver_Interface.sol";

import "./ERC223_Interface.sol";

 

 /** * ERC223 token by Dexaran * * https://github.com/Dexaran/ERC223-token-standard */

 

 

 /* https://github.com/LykkeCity/EthereumApiDotNetCore/blob/master/src/ContractBuilder/contracts/token/SafeMath.sol */

contract SafeMath {

    uint256 constant public MAX_UINT256 =

    0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

 

    function safeAdd(uint256 x, uint256 y) constant internal returns (uint256 z) {

        if (x > MAX_UINT256 - y) revert();

        return x + y;

    }

 

    function safeSub(uint256 x, uint256 y) constant internal returns (uint256 z) {

        if (x < y) revert();

        return x - y;

    }

 

    function safeMul(uint256 x, uint256 y) constant internal returns (uint256 z) {

        if (y == 0) return 0;

        if (x > MAX_UINT256 / y) revert();

        return x * y;

    }

}

 

/**

ERC223示例的智能合約代碼

*/

contract ERC223Token is ERC223, SafeMath {

 

    mapping(address => uint) balances;

 

    string public name;

    string public symbol;

    uint8 public decimals;

    uint256 public totalSupply;

 

 

    // 獲取token的名稱

    function name() public view returns (string) {

        return name;

    }

    // 獲取token的符號

    function symbol() public view returns (string) {

        return symbol;

    }

    // 獲取token精確到小數點后的位數

    function decimals() public view returns (uint8) {

        return decimals;

    }

    // 獲取token的發布總量

    function totalSupply() public view returns (uint256) {

        return totalSupply;

    }

 

 

    // 當用戶或其他合同想要轉移資金時調用的功能。

    function transfer(address _to, uint _value, bytes _data, string _custom_fallback) public returns (bool success) {

        //如果to是合約

        if(isContract(_to)) {

            if (balanceOf(msg.sender) < _value) revert(); //如果當前的余額不夠就拋出

            balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);//發送者的余額做減法

            balances[_to] = safeAdd(balanceOf(_to), _value); //接收者的余額做加法

            ContractReceiver receiver = ContractReceiver(_to);   //初始化接收合約,構造函數參數為接收者的合約地址

            receiver.call.value(0)(bytes4(sha3(_custom_fallback)), msg.sender, _value, _data);

            Transfer(msg.sender, _to, _value, _data);

            return true;

        }

        else {

            return transferToAddress(_to, _value, _data);

        }

    }

 

 

    // 當用戶或其他合同想要轉移資金時調用的功能。

    function transfer(address _to, uint _value, bytes _data) public returns (bool success) {

 

        if(isContract(_to)) {

            return transferToContract(_to, _value, _data);

        }

        else {

            return transferToAddress(_to, _value, _data);

        }

    }   

 

    // 類似於ERC20傳輸的標准功能傳輸,沒有_data。

    // 由於向后兼容性原因而增加。

    function transfer(address _to, uint _value) public returns (bool success) {

 

        //類似於沒有_data的ERC20傳輸的標准功能傳輸

        //由於向后兼容性原因而增加

        bytes memory empty;

        if(isContract(_to)) {//如果是合約

            return transferToContract(_to, _value, empty);

        }

        else {

            return transferToAddress(_to, _value, empty);

        }

    }

 

    /**

    判斷某賬戶地址是EOA地址還是合約地址

    組裝定地址字節碼。 如果存在字節碼,那么_addr是一個合約。

    */

    function isContract(address _addr) private returns (bool is_contract) {

        uint length;

        Assembly {

              //檢索目標地址上的代碼大小,這需要匯編

              length := extcodesize(_addr)

        }

        return (length>0);

    }

 

    /**

    當傳遞目標是一個地址【即: 外部賬戶】時調用函數

    */

    function transferToAddress(address _to, uint _value, bytes _data) private returns (bool success) {

        if (balanceOf(msg.sender) < _value) revert();

        balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);

        balances[_to] = safeAdd(balanceOf(_to), _value);

        Transfer(msg.sender, _to, _value, _data);

        return true;

    }

 

    /**

    當傳遞目標是一個合約【合約賬戶】時調用函數

    【注意】token接收者是合約的話,需要調用 自定義的具備了 tokenFallback函數的 合約對象的tokenFallback函數 【要求接受token的合約必須具備了tokenFallback函數】

    */

    function transferToContract(address _to, uint _value, bytes _data) private returns (bool success) {

        if (balanceOf(msg.sender) < _value) revert();

        balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);

        balances[_to] = safeAdd(balanceOf(_to), _value);

        ContractReceiver receiver = ContractReceiver(_to);

        receiver.tokenFallback(msg.sender, _value, _data); //必須要調用這個回調

        Transfer(msg.sender, _to, _value, _data);

        return true;

    }

 

 

    //得到_owner的余額

    function balanceOf(address _owner) public constant returns (uint balance) {

        return balances[_owner];

    }

}
View Code

以上ERC223標准的token發幣合約示例表示,當需要調用交易函數把ERC223標准token交易給某個合約地址時,要求合約必須具備tokenFallback函數【合約開發人員希望他們的合約使用指定的token,那么合約開發人員必須實現tokenFallback,並使用參數address,uint256,bytes。 此函數必須具有0xc0ee0b8a簽名】,否則轉賬失敗;現有的代幣肯定是大部分基於 ERC20 標准的,遷移難度很大,畢竟這個事情需要大家一起動。至於新的代幣,很多已經開始使用 ERC223 標准了,目前已經超過了三萬種(某位網上的博主說的,不是我說的。。。)

 

以上介紹了兩種可以發行 【可代替性通證】的合約,(可代替性就是可以代替所有沒有唯一性的事物,如:錢、積分等);

 

3.ERC721

下面開始研究針對【不可代替性的事物】的一些合約標准,【CryptoKitties 以太貓】相信大家都對這款曾經讓以太坊網絡一度癱瘓的 貓科動物繁殖類無聊燒錢游戲有一點點耳聞吧?下面是代碼:

pragma solidity ^0.4.16;

/**

以太貓使用的ERC721的合約標准

 */

contract ERC721 {

    // Required method

    function totalSupply() public constant returns (uint256 totalSupply);

    function balanceOf(address _owner) public constant returns (uint256 balance);

    /**

    根據代幣Id查詢代幣持有者

     */

    function ownerOf(uint256 _tokenId) public constant returns (address _owner);

    function transfer(address _to, uint256 _tokenId) public;

    function approve(address _to, uint256 _tokenId) public;

    /**

    在Approve 允許的條件下, 交易方msg.sender 調用該函數可以指定_tokenId的代幣從他人那轉至自己名下

    類似於ERC20的 transferFrom

     */

    function takeOwnership(uint256 _tokenId) public;

 

    // Optional method

    function name() public constant returns (string name);

    function symbol() public constant returns (string symbol);

    /**

    根據持有者和索引查詢所持有的代幣

     */

    function tokenOfOwnerByIndex(address _owner, uint256 _index) public constant returns (uint tokenId);

    /**

    查看代幣的元數據

    根據代幣Id查詢到元數據對應的URL, 里面包含了 代幣名稱,圖像和描述等

     */

    function tokenMetadata(uint256 _tokenId) public constant returns (string infoUrl);

 

    // Events

    event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);

    event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);

}

 
View Code

可以看到ERC721協議其實和ERC20協議還是很類似的,代幣名稱、代幣符號、代幣支持的小數位等等,然后在這基礎上做了點改動,因為在ERC721中每個代幣都將是唯一的一串Hash碼,且代幣是可以在各個持有者間相互轉讓的;所以有具備查詢代幣持有者地址的ownerOf函數、有根據持有者及索引查詢持有的某個代幣的tokenOfOwnerByIndex函數等等以上在代碼里面都有所說明,這里就不做贅述;

4.ERC1155

首先,我們要說下不管是ERC20系【可替代性通證】還是ERC721系【不可替代性通證】的token都具備的一個問題,對於一個項目中如果有幾萬種完全不同性質的東西,比如: 錢是錢、積分是積分、收藏品是收藏品那么我們需要部署幾萬種token的合約【不管是ERC20的還是ERC721的】那么問題來了,首先這幾萬種合約里面必然有大量的重復代碼,但是礦工們依然會把這幾萬種合約都上鏈,【注意我說的是在一個項目里面,比如: 游戲項目】,所以給每一個不同的物品設立一個獨立的合約,這產生的巨大成本和之后帶來的管理費用,都將是幾乎讓人無法承受的,那么ERC1155就是為了解決這種問題而生的,現在『物品』(可能包含ERC20的token或ERC721的token或兩者都有)可以被單一的一個合約(打包處理)來定義了。合約里包含區別token們所需的最小量的數據。好比,后來出現的視頻壓縮技術,后一幀只記錄了與前一幀的不同之處,所以極大的壓縮了整個視頻的體積,合約的狀態包含了每個token ID的配置信息和管理收集的所有行為。ERC-1155的靈活性更強,它使得開發者可以自行選擇是批量生成某一種特定的token,還是構建不可被復制的惟一元數據;說白點就是說ERC1155可以把一種token換成為另外一種token,最大進步就是可以融合不同token(可能是『可替換』的代幣與『不可替換』的代幣的混合體)進行『打包處理』;下面是一個ERC1155的合約標准

pragma solidity ^0.4.16;

 

/**

針對 可替代token的

 

https://github.com/ethereum/EIPs/issues/1155

 */

contract ERC1155 {

    // Events

    event Approval(address indexed _owner, address indexed _spender, uint256 indexed _itemId, uint256 _value);

    event Transfer(address indexed _from, address indexed _to, uint256 indexed _itemId, uint256 _value);

 

    // Required Functions

 

    /**

    【兩個方法一個處理單個的一個批量處理】 【請參照 ERC20的transfer函數】

    將每個itemId[]的數量轉移到指定的地址。

    每個參數數組應該是相同的長度,每個索引都是相關的。

    必須觸發 Transfer事件

    itemId 可以看做是某個特定的tokenId

     */

    function transfer(address _to, uint256 _itemId, uint256 _value) external;

    function batchTransfer(address _to, uint256[] _itemIds, uint256[] _values) external;

 

    /**

    【兩個方法一個處理單個的一個批量處理】 【請參照 ERC20的transferFrom函數】

    將每一個itemId[]的數量從一個或多個地址轉移到指定地址。

    每個參數數組應該是相同的長度,每個索引都是相關的

    必須觸發 Transfer事件

    itemId 可以看做是某個特定的tokenId

     */

    function transferFrom(address _from, address _to, uint256 _itemId, uint256 _value) external;

    function batchTransferFrom(address _from, address _to, uint256[] _itemIds, uint256[] _values) external;

    

    /**

    【兩個方法一個處理單個的一個批量處理】 【請參照 ERC20的approve函數】

    批准一個帳戶可以替代表另一個帳戶(使用轉賬)轉移最大數量的多個itemId數目

    必須觸發 Approval事件

     */

    function approve(address _spender, uint256 _itemId, uint256 _value) external;

    function batchApprove(address _spender, uint256[] _itemIds,  uint256[] _values) external;

    

    /**

    增加一個或多個itemId的余量,而不需要重置為0 【及變更approve函數指定的允許轉移量??】

    必須觸發 Approval事件

     */

    function increaseApproval(address _spender, uint256 _itemId,  uint256 _addedValue) external;

    function batchIncreaseApproval(address _spender, uint256[] _itemIds,  uint256[] _addedValues) external;

    

    /**

    減少一個或多個itemId的余量,而不需要重置為0

    必須觸發 Approval事件

     */

    function decreaseApproval(address _spender, uint256 _itemId,  uint256 _subtractedValue) external;

    function batchDecreaseApproval(address _spender, uint256[] _itemIds,  uint256[] _subtractedValues) external;

 

    // Required View Functions

    function totalSupply(uint256 _itemId) external view returns (uint256);

    /**

    根據對應的tokenId查看余額

     */

    function balanceOf(uint256 _itemId, address _owner) external view returns (uint256);

    /**

    根據對應的tokenId及擁有者及代替擁有者花錢者(注意 錢還是話擁有者的,只是擁有者給予某些權力給 第三者可以挪用她的部分資金) 具體參照ERC20 自明

     */

    function allowance(uint256 _itemId, address _owner, address _spender) external view returns (uint256);

 

    // Optional View Functions

    function name(uint256 _itemId) external view returns (string);

    function symbol(uint256 _itemId) external view returns (string);

    function decimals(uint256 _itemId) external view returns (uint8);

}

 

/**

針對不可替代token的拓展

 */

contract ERC1155NonFungible {

    // Optional Functions for Non-Fungible Items

    /**

    For NFTs, this returns the owner of a specific _itemId.

    在【 Non-Fungible Items】,返回當前tokenId 所屬者 【參照ERC721】

     */

    function ownerOf(uint256 _itemId) external view returns (address);

    /**

    返回當前tokenId的描述的URL 【參照ERC721】

     */

    function itemURI(uint256 _itemId) external view returns (string);

    /**

    列舉可用的Non-Fungible Items

     */

    function itemByIndex(uint256 _itemId, uint128 _index) external view returns (uint256);

    /**

    列舉分配給所有者的Non-Fungible Items

     */

    function itemOfOwnerByIndex(uint256 _itemId, address _owner, uint128 _index) external view returns (uint256);

}

 
View Code

基本上就是ERC1155的注釋說明。

5.ERC165

自己看注釋就知道ERC165是干什么的了,順便說一下CryptoKities合約里面有實現了ERC165的。

/**

這個才是 ERC165 標准

就是一個接口 里面就一個方法

創建標准方法以發布和檢測智能合約實現的接口

 

ERC165同樣是一個合約標准,這個標准要求合約提供其實現了哪些接口,

這樣再與合約進行交互的時候可以先調用此接口進行查詢。

interfaceID為函數選擇器,計算方式有兩種,

如:bytes4(keccak256('supportsInterface(bytes4)'));

或ERC165.supportsInterface.selector,多個函數的接口ID為函數選擇器的異或值

 

此功能必須返回一個bool並使用最多30,000gas

 */

interface ERC165 {

    /// @notice Query if a contract implements an interface

    /// @param interfaceID The interface identifier, as specified in ERC-165

    /// @dev Interface identification is specified in ERC-165. This function

    ///  uses less than 30,000 gas.

    /// @return 'true' if the contract implements 'interfaceID' and

    ///  'interfaceID' is not 0xffffffff, 'false' otherwise

    function supportsInterface(bytes4 interfaceID) external view returns (bool);

}
View Code

OK〜 因為這一些列的問題實在是太多了如果想看,請自行去github 中里Ethereum的EIPs里面的issue里面去看吧,(注:想看什么標准就看問是否有,我們可以這樣看https://github.com/ethereum/EIPs/issues/XXX,其中XXX就是ERCXXX里面的數字也就是ERC20。

例如:https://github.com/ethereum/EIPs/issues/20

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM