
1,摘要
【本文目標(biāo)】
通過本文學(xué)習(xí),了解ERC定義及知名ERC協(xié)議標(biāo)準(zhǔn),如ERC20以及ERC223、ERC621,ERC777,ERC827,ERC1410協(xié)議; ERC721以及 ERC875,ERC1155,ERC998協(xié)議,ERC 865等描述和定義。
2,ERC的定義及標(biāo)準(zhǔn)列表
ERC代表“Ethereum Request for Comment",這是Ethereum版的意見征求稿 (RFC),RFC是由互聯(lián)網(wǎng)工程任務(wù)組制定的一個概念。 RFC中的備忘錄包含技術(shù)和組織注意事項。 對于ERC,意見征求稿中包括一些關(guān)于以太坊網(wǎng)絡(luò)建設(shè)的技術(shù)指導(dǎo)。
ERC是Ethereum開發(fā)者為以太坊社區(qū)編寫的。 因此,ERC的創(chuàng)建流程中包括開發(fā)人員。 為了創(chuàng)建一個以太坊平臺的標(biāo)準(zhǔn),開發(fā)人員應(yīng)當(dāng)提交了一個以太坊改進方案(EIP,Ethereum Improvement Protocol), 改進方案中包括協(xié)議規(guī)范和合約標(biāo)準(zhǔn)。 一旦EIP被委員會批準(zhǔn)并最終確定,它就成為ERC。 EIP的完整原始信息可以在GITHUB網(wǎng)址找到。
EIP提案首先需要進行一個嚴(yán)格的驗收進程,大致包括了以下四個步驟:
1)如果開發(fā)人員對軟件改動有了新的想法,這個想法應(yīng)該以拉取請求(pull request)的形式呈現(xiàn)出來。在一個拉取請求中,改動能夠在提案中輕易完成,同時積極聽取社區(qū)的反饋。在這里,它屬于EIP編輯的審查改動范圍內(nèi)。
2)如果EIP編輯認(rèn)為這個請求在技術(shù)上沒有錯誤的地方,并且符合以太坊的社區(qū)價值觀,他們會將其作為草稿合并到下一個階段中。
3)在合并之后,如Geth何Parity等以太坊各式各樣的軟件應(yīng)用才會誕生,并且如果它們能真的運作起來,這個提案最終被看作是“已接受”。
4) 一旦接受以后,整個平臺就會根據(jù)這個EIP提供的用以運行以太坊軟件的多樣代碼來進行升級。
相應(yīng)的EIP對應(yīng)有4種狀態(tài):
草稿(Draft) - 處于打開狀態(tài),便于考察討論;
接受(Accepted) - 即將被接受,例如將包含在下一個硬分叉中;
定稿(Final)- 在上一個硬分叉中被接受,已定稿;
延期(Deferred)- 不會馬上被接受,但也許在將來的硬分叉版本會考慮。
最終確定的EIP為以太坊開發(fā)者提供了一套可實施的標(biāo)準(zhǔn)。 這使得智能合約可以遵循這些通用的接口標(biāo)準(zhǔn)來構(gòu)建。EIP的狀態(tài)列表可以在https://eips.ethereum.org/all找到,它的主要分類見下圖:

截止到目前,ERC家族Final可以用下圖表示:

ERC-20是整個加密社區(qū)中最為人熟知的標(biāo)準(zhǔn),在Ethereum平臺之上發(fā)布的大多數(shù)通證(token)都使用它。
3,ERC20系列 - ERC20、ERC223、ERC621, ERC777,ERC827,ERC1400
3.1 ERC20標(biāo)準(zhǔn)
-
狀態(tài):
定稿(Final) -
提交記錄:
https://github.com/ethereum/EIPs/issues/20 -
標(biāo)準(zhǔn)說明:
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md -
推薦樣例:
https://github.com/OpenZeppelin/openzeppelin-solidity/tree/master/contracts/token/ERC20
ERC-20標(biāo)準(zhǔn)中定義了以下函數(shù)接口:
-
totalSupply():
返回代幣供給總量 -
balanceOf(address _owner):
返回_owner的帳戶余額 -
transfer(address _to,uint256 _value):
并將數(shù)量為_value的代幣轉(zhuǎn)入地址_to并觸發(fā)transfer事件 -
transferFrom(address _from,address _to,uint256_value):
將地址_from中的_value數(shù)量的代幣轉(zhuǎn)入地址_to ,并觸發(fā)transfer事件 -
approve(address _spender,uint256 _value):
允許_spender提取限額_value的代幣 -
allowance(address _owner,address _spender):
返回_spender可從_owner提款的代幣數(shù)量上限
ERC-20于2015年提出并于2017年9月正式實施。這是代幣標(biāo)準(zhǔn)化的一個很好的起點。 然而,開發(fā)者社區(qū) 已經(jīng)注意到它存在一些缺陷和漏洞,此外,還有一些場景它不能很好的滿足。因此陸續(xù)提出了其他的ERC標(biāo)準(zhǔn)。
3.2 ERC223
-
狀態(tài):
草稿(Draft) -
提交記錄:
https://github.com/ethereum/EIPs/issues/223 -
標(biāo)準(zhǔn)說明:
https://github.com/Dexaran/ERC223-token-standard -
推薦樣例:
https://github.com/Dexaran/ERC223-token-standard/tree/Recommended
開發(fā)人員Dexaran在一篇文章中詳細描述了ERC20不適合的兩種場景:
“在ERC20中執(zhí)行交易有兩種方式:transfer函數(shù),approve + transferFrom機制,通證余額只是通證合約中的一個變量。
通證的交易是合約內(nèi)部變量的變化。 轉(zhuǎn)出賬戶的余額將減少,轉(zhuǎn)入賬戶的余額將增加。
交易發(fā)生時, transfer()函數(shù)不會通知轉(zhuǎn)入賬戶。 因此轉(zhuǎn)入賬戶將無法識別傳入的交易! 我寫了一個例子,可以展示這一導(dǎo)致未處理的交易和資金損失的過程 。
因此,如果接收賬戶是合約賬戶,那么必須使用approve + transferFrom機制來發(fā)送通證。
如果接受賬戶是外部帳戶,則必須通過transfer函數(shù)發(fā)送通證。 如果選擇了錯誤的機制,通證將卡在合約內(nèi)(合約將不會識別交易),沒有辦法來提取這些卡殼的通證?!?br>
他對這個問題提出的解決方案包含在ERC-223中 。 它與ERC-20標(biāo)準(zhǔn)非常相似,但解決了上述問題。當(dāng)通證轉(zhuǎn)移到智能合約賬戶時,該合約的特殊函數(shù)tokenFallback() 允許接收方合約拒絕通證或觸發(fā)進一步的操作。 大多數(shù)情況下,這可以用來代替approve()函數(shù)。
函數(shù)接口:
transfer(address _to, uint _value):
會區(qū)分代幣是發(fā)往外部賬戶地址還是發(fā)往智能合約地址。
transfer(address _to, uint _value, bytes _data):
會區(qū)分代幣是發(fā)往外部賬戶地址還是發(fā)往智能合約地址,還可以傳送數(shù)據(jù)。
- 1、如果_to是合約,則此函數(shù)必須傳輸通證并調(diào)_to中的函數(shù)tokenFallback(address,uint256,bytes)。
- 2、如果_to(接收方合約)中沒有實現(xiàn)tokenFallback函數(shù),則事務(wù)必須失敗,并且不會發(fā)生通證的傳輸。
- 3、如果_to是外部擁有的地址,則必須發(fā)送事務(wù),而不嘗試在_to中執(zhí)行tokenFallback。
- 4、_data可以附加到這個通證(token)交易中,它將永遠保持在塊狀(需要更多的gas)。 _data可以是空的。
注意:檢查_to是合約還是地址的推薦方法是組裝_to的代碼。 如果_to中沒有代碼,那么這是一個外部擁有的地址,否則就是一個合約。
//assemble the given address bytecode. If bytecode exists then the _addr is a contract.
function isContract(address _addr) private view returns (bool is_contract) {
uint length;
assembly {
//retrieve the size of the code on target address, this needs assembly
length := extcodesize(_addr)
}
return (length>0);
}
function tokenFallback(address _from, uint _value, bytes _data)
_from是通證(token)發(fā)送者,_value是傳入通證(token)的數(shù)量,_data是附加的數(shù)據(jù),類似于Ether事務(wù)中的數(shù)據(jù)。 適用于以太交易的回退功能,并且不返回任何內(nèi)容。
tokenFallback -- 通證(token)持有者發(fā)送通證(token)時處理從通證(token)合約所調(diào)用的通證(token)傳輸?shù)墓δ?/p>
注意:msg.sender將是tokenFallback函數(shù)內(nèi)的通證(token)合約。 過濾哪些通證(token)(通過通證(token)契約地址)發(fā)送可能很重要。 通證(token)發(fā)送者(誰發(fā)起了代幣交易的人)在_from thetokenFallback函數(shù)內(nèi)。
示例代碼:
ERC223_Interface.sol
pragma solidity ^0.4.9;
/* 新的 ERC23 contract 接口文件 */
contract ERC223 {
uint public totalSupply;
function balanceOf(address who) constant returns (uint);
function name() constant returns (string _name);
function symbol() constant returns (string _symbol);
function decimals() constant returns (uint8 _decimals);
function totalSupply() constant returns (uint256 _supply);
function transfer(address to, uint value) returns (bool ok);
function transfer(address to, uint value, bytes data) returns (bool ok);
function transfer(address to, uint value, bytes data, string custom_fallback) returns (bool ok);
event Transfer(address indexed from, address indexed to, uint value, bytes indexed data);
}
Receiver_Interface.sol
pragma solidity ^0.4.9;
/*
* Contract that is working with ERC223 tokens
*/
contract ContractReceiver {
struct TKN {
address sender; //調(diào)用合約的人
uint value;
bytes data;
bytes4 sig; //簽名
}
function tokenFallback(address _from, uint _value, bytes _data){
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是發(fā)起這個通證(token)交易的人(類似于msg.sender)
* tkn.value發(fā)送的通證(token)數(shù)(msg.value的類比)
* tkn.data是通證(token)交易的數(shù)據(jù)(類似于msg.data)
* tkn.sig是4字節(jié)的功能簽名
* 如果通證(token)事務(wù)的數(shù)據(jù)是一個函數(shù)執(zhí)行
*/
}
}
ERC223_Token.sol
pragma solidity ^0.4.9;
import "./Receiver_Interface.sol";
import "./ERC223_Interface.sol";
/**
* ERC23 token by Dexaran
*
* https://github.com/Dexaran/ERC23-tokens
* 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) throw;
return x + y;
}
function safeSub(uint256 x, uint256 y) constant internal returns (uint256 z) {
if (x < y) throw;
return x - y;
}
function safeMul(uint256 x, uint256 y) constant internal returns (uint256 z) {
if (y == 0) return 0;
if (x > MAX_UINT256 / y) throw;
return x * y;
}
}
//示例的智能合約代碼
contract ERC223Token is ERC223, SafeMath {
mapping(address => uint) balances;
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
// 獲取token的名稱
function name() constant returns (string _name) {
return name;
}
// 獲取token的符號
function symbol() constant returns (string _symbol) {
return symbol;
}
// 獲取token精確到小數(shù)點后的位數(shù)
function decimals() constant returns (uint8 _decimals) {
return decimals;
}
// 獲取token的發(fā)布總量
function totalSupply() constant returns (uint256 _totalSupply) {
return totalSupply;
}
// 當(dāng)用戶或其他合約想要轉(zhuǎn)移資金時調(diào)用的功能。
function transfer(address _to, uint _value, bytes _data, string _custom_fallback) returns (bool success) {
//如果to是合約
if(isContract(_to)) {
if (balanceOf(msg.sender) < _value) throw; //如果當(dāng)前的余額不夠就拋出
balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);//發(fā)送者的余額做減法
balances[_to] = safeAdd(balanceOf(_to), _value); //接收者的余額做加法
ContractReceiver receiver = ContractReceiver(_to); //初始化接收合約,構(gòu)造函數(shù)參數(shù)為接收者的合約地址
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);
}
}
// 當(dāng)用戶或其他合約想要轉(zhuǎn)移資金時調(diào)用的功能。
function transfer(address _to, uint _value, bytes _data) returns (bool success) {
if(isContract(_to)) {
return transferToContract(_to, _value, _data);
}
else {
return transferToAddress(_to, _value, _data);
}
}
// 類似于ERC20傳輸?shù)臉?biāo)準(zhǔn)功能傳輸,沒有_data。
// 由于向后兼容性原因而增加。
function transfer(address _to, uint _value) returns (bool success) {
//類似于沒有_data的ERC20傳輸?shù)臉?biāo)準(zhǔn)功能傳輸
//由于向后兼容性原因而增加
bytes memory empty;
if(isContract(_to)) {//如果是合約
return transferToContract(_to, _value, empty);
}
else {
return transferToAddress(_to, _value, empty);
}
}
//組裝定地址字節(jié)碼。 如果存在字節(jié)碼,那么_addr是一個合約。
function isContract(address _addr) private returns (bool is_contract) {
uint length;
assembly {
//檢索目標(biāo)地址上的代碼大小,這需要匯編
length := extcodesize(_addr)
}
return (length>0);
}
//當(dāng)傳遞目標(biāo)是一個地址時調(diào)用函數(shù)
function transferToAddress(address _to, uint _value, bytes _data) private returns (bool success) {
if (balanceOf(msg.sender) < _value) throw;
balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);
balances[_to] = safeAdd(balanceOf(_to), _value);
Transfer(msg.sender, _to, _value, _data);
return true;
}
//當(dāng)傳遞目標(biāo)是一個合約時調(diào)用函數(shù)
function transferToContract(address _to, uint _value, bytes _data) private returns (bool success) {
if (balanceOf(msg.sender) < _value) throw;
balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);
balances[_to] = safeAdd(balanceOf(_to), _value);
ContractReceiver receiver = ContractReceiver(_to);
receiver.tokenFallback(msg.sender, _value, _data); //必須要調(diào)用這個回調(diào)
Transfer(msg.sender, _to, _value, _data);
return true;
}
//得到_owner的余額
function balanceOf(address _owner) constant returns (uint balance) {
return balances[_owner];
}
}
3.3 ERC621
狀態(tài):
草稿(Draft)標(biāo)準(zhǔn)說明:
推薦樣例:
https://github.com/skmgoldin/EIP621Token/blob/master/contracts/EIP621Token.sol
ERC-621是ERC-20標(biāo)準(zhǔn)的擴展。 它增加了兩個額外的功能, increaseSupply和decreaseSupply 。這可以增加和減少流通中的通證(token)供應(yīng)。 ERC-20只允許單一的通證發(fā)放事件。 這將供應(yīng)量限制在一個固定的不可改變的數(shù)目。 ERC-621建議totalSupply應(yīng)當(dāng)是可修改的。
接口函數(shù)說明:
increaseSupply(uint value, address to):
可以給特定賬戶to增加value值的供應(yīng)量,代幣總供應(yīng)量totalSupply也同步增加;
decreaseSupply(uint value, address from):
可以給特定賬戶to減少value值的賬戶余額,代幣總供應(yīng)余額totalSupply也同步減少;
3.4 ERC777
狀態(tài):
草稿(Draft)標(biāo)準(zhǔn)說明:
https://eips.ethereum.org/EIPS/eip-777推薦樣例:
https://github.com/jacquesd/ERC777/tree/devel/contracts
功能描述
本標(biāo)準(zhǔn)用于提升ERC20標(biāo)準(zhǔn)的使用范圍。這個標(biāo)準(zhǔn)的主要優(yōu)點有:
- 可以同使用Ether一樣的原理使用ERC777通證,通證發(fā)送采用函數(shù)
send(dest, value, data)的。 - 不管是合約還是常規(guī)的地址都可以控制和拒絕那些通過注冊
tokensToSend鉤函數(shù)發(fā)送的通證(通過在鉤函數(shù)內(nèi)部執(zhí)行reverting回滾函數(shù)觸發(fā)拒絕。) - 不管是合約還是常規(guī)的地址都可以控制和拒絕那些通過注冊
tokensToSend鉤函數(shù)接收的通證(通過在鉤函數(shù)內(nèi)部執(zhí)行reverting回滾函數(shù)觸發(fā)拒絕。) -
tokensReceived勾函數(shù)運行發(fā)送通證給一個合約,并在一次交易中通知完成,不像ERC20需要2次通知(approve/transferFrom) 才能達到相同效果。 - 通證持有者可以“授權(quán)”和“撤銷”可以代表他們發(fā)送通證的操作員。這些操作員用于驗證合約,如交易所,支票處理器或自動收費系統(tǒng)。
- 每次通證交易都包含一個“data”字節(jié)字段和一個類似的“operatorData”,可以自由地用于將數(shù)據(jù)傳遞給接收方。
- 通過部署實現(xiàn)錢包的“tokensReceived”鉤子的代理合約,它與不包含“tokensReceived”鉤子功能的錢包向后兼容。
協(xié)議代碼
interface ERC777Token {
function name() public view returns (string);
function symbol() public view returns (string);
function totalSupply() public view returns (uint256);
function balanceOf(address owner) public view returns (uint256);
function granularity() public view returns (uint256);
function defaultOperators() public view returns (address[]);
function authorizeOperator(address operator) public;
function revokeOperator(address operator) public;
function isOperatorFor(address operator, address tokenHolder) public view returns (bool);
function send(address to, uint256 amount, bytes data) public;
function operatorSend(address from, address to, uint256 amount, bytes data, bytes operatorData) public;
function burn(uint256 amount, bytes data) public;
function operatorBurn(address from, uint256 amount, bytes data, bytes operatorData) public;
event Sent(
address indexed operator,
address indexed from,
address indexed to,
uint256 amount,
bytes data,
bytes operatorData
);
event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
event Burned(address indexed operator, address indexed from, uint256 amount, bytes operatorData);
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
event RevokedOperator(address indexed operator, address indexed tokenHolder);
}
3.5 ERC827
狀態(tài):
草稿(Draft)標(biāo)準(zhǔn)說明:
推薦樣例:
https://github.com/windingtree/erc827/blob/master/contracts/ERC827/ERC827Token.sol
它允許轉(zhuǎn)讓通證并允許持有人允許第三方使用通證。 以太坊上的通證可以被其他應(yīng)用程序重復(fù)使用,這其中也包括錢包和交易所。 當(dāng)需要支持第三方動態(tài)消費限額調(diào)整時這一點非常有用。
該標(biāo)準(zhǔn)目前處于草稿狀態(tài),并被證明有使用安全風(fēng)險,建議暫不使用。
4,ERC721系列
4.1 ERC721
-
狀態(tài):
定稿(Final) -
提交記錄:
https://github.com/ethereum/EIPs/issues/721 -
標(biāo)準(zhǔn)說明:
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md -
推薦樣例:
1)https://www.cryptokitties.co/
2)https://github.com/OpenZeppelin/openzeppelin-solidity/tree/master/contracts/token/ERC721
ERC-721與ERC-20和ERC-223都大不相同。 它描述了一個不可互換的通證,官方簡要解釋是Non-Fungible Tokens,簡寫為NFTs,多翻譯為非同質(zhì)代幣。 這意味著每個通證是完全不同的,并且每個通證對不同的用戶都有不同的價值。 理解這種通證的一個方法就是回憶CryptoKittes。 每一個數(shù)字貓都是獨立的,其價值取決于其稀缺性和用戶的購買欲。
ERC-721通證(token)可用于任何交易所,但通證價值是“每個通證的唯一性和稀缺性所決定的結(jié)果”。標(biāo)準(zhǔn)中規(guī)定的接口函數(shù)包括name、symbol、totalSupply、balanceOf、ownerOf、approve、takeOwnership 、 transfer 、tokenOfOwnerByIndex和tokenMetadata 。 它還定義了兩個事件: Transfer和Approval 。 Gerald Nash的 這篇文章很好地解釋了可互換性的概念。
函數(shù)接口說明:
-
balanceOf(address _owner):
返回由_owner 持有的NFTs的數(shù)量。 -
ownerOf(uint256 _tokenId):
返回tokenId代幣持有者的地址。 -
exists(uint256 _tokenId):
tokenId代幣是否存在,返回BOOL值; -
approve(address _to, uint256 _tokenId):
授予地址_to具有_tokenId的控制權(quán),方法成功后需觸發(fā)Approval 事件。 -
getApproved(uint256 _tokenId):
獲得_tokenId授權(quán)的地址; -
setApprovalForAll(address _operator, bool _approved):
授予地址_operator具有所有NFTs的控制權(quán),成功后需觸發(fā)ApprovalForAll事件。 -
isApprovedForAll(address _owner, address _operator):
用來查詢授權(quán)。 -
transferFrom(address _from, address _to, uint256 _tokenId)
不建議使用本函數(shù),建議使用safeTransferFrom函數(shù)。 -
safeTransferFrom(address _from, address _to, uint256 _tokenId):
把_tokenId代幣從_from賬戶安全轉(zhuǎn)移到_to賬戶,安全是指如果目標(biāo)地址為合約地址,則執(zhí)行onERC721Received進行資產(chǎn)轉(zhuǎn)移,否則的話交易會回滾;如果目標(biāo)地址為外部賬號地址,則正常轉(zhuǎn)移。
更深度分析的文章參考《【基于ERC721的區(qū)塊鏈游戲】迷戀貓從玩耍到開發(fā)》。
4.2 ERC875
狀態(tài):
還處于pull request下(issue)標(biāo)準(zhǔn)說明:
AlphaWallet自主開發(fā)了ERC875協(xié)議族。該協(xié)議不僅會讓數(shù)字資產(chǎn)變得具有收藏價值,同時也能幫助現(xiàn)實世界中不可拆分替代、具有物權(quán)唯一性的資產(chǎn)上鏈,這就能為線下服務(wù)的鏈上操作提供了可能性。
雖然另一種協(xié)議ERC721也能實現(xiàn)token的不可置換性,但其存在需要交易雙方支付gas費用、無法簡單實現(xiàn)原子化交易等一些不易于用戶使用的問題。
ERC875內(nèi)置了兩個密碼學(xué)協(xié)議, 一方面能夠簡單實現(xiàn)原子化交易(atomic swap)——直接搭建去中心化市場、降低普通用戶使用門檻,賣家無需持有以太幣,買家支付一次gas即能完成;另外一方面可以簡單打包處理大量交易。
拿基于ERC721的加密貓來說,換用ERC875協(xié)議的話,能夠?qū)崿F(xiàn)。用戶在商家網(wǎng)站法幣購貓,通過MagicLink免費把貓導(dǎo)入用戶的錢包,之后用戶還可以在不需要持有以太幣的情況下,通過MagicLink把貓售出或者免費轉(zhuǎn)讓,全部過程都是無中心的原子化交易。另外商家可以一次批發(fā)100只貓給分銷商。
接口函數(shù)或者變量說明
- totalTickets:
- inventory:
- ticketIndex:
- expiryTimeStamp:
- owner:
- admin:
- transferFee:
- numOfTransfers:
- name:
- symbol:
- decimals:
-
Token(uint256[] numberOfTokens, string evName,uint expiry, string eventSymbol, address adminAddr):
構(gòu)建函數(shù),樣例如example: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], "MJ comeback", 1603152000, "MJC", "0x007bEe82BDd9e866b2bd114780a47f2261C684E3"] -
getDecimals():
返回代幣的小數(shù)點后位數(shù)值; -
trade(uint256 expiry,uint256[] tokenIndices,uint8 v,bytes32 r,bytes32 s):
交易函數(shù),例如:0, [3, 4], 27, "0x2C011885E2D8FF02F813A4CB83EC51E1BFD5A7848B3B3400AE746FB08ADCFBFB", "0x21E80BAD65535DA1D692B4CEE3E740CD3282CCDC0174D4CF1E2F70483A6F4EB2" - encodeMessage(bytes12 prefix, uint value,uint expiry, uint256[] tokenIndices):
-
name():
返回代幣名稱; -
symbol():
返回代幣表示; -
getAmountTransferred():
返回已傳輸?shù)臄?shù)量; -
isContractExpired():
合約是否過期; -
balanceOf(address _owner):
返回賬戶余額; - myBalance():
-
transfer(address _to, uint256[] tokenIndices):
資產(chǎn)轉(zhuǎn)賬; - transferFrom(address _from, address _to, uint256[] tokenIndices):
-
endContract():
結(jié)束合約; -
getContractAddress():
獲取合約地址;
4.3 ERC998
狀態(tài):
草稿(Draft)標(biāo)準(zhǔn)說明:
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-998.md
不同的ERC代幣可以被兼容的ERC-998代幣既代表一組相似資產(chǎn)(ERC-20代幣),一種獨特資產(chǎn)的分類(ERC-721代幣),或者內(nèi)嵌于單比交易的混合體。
這個協(xié)議是以不可以替代代幣為基礎(chǔ)的全新復(fù)雜型數(shù)字資產(chǎn)。一個ERC-998代幣可以作為一個數(shù)字資產(chǎn)投資組合。
中心資產(chǎn)和輔助資產(chǎn)的結(jié)合
第一個使用案例是可以和不同數(shù)字資產(chǎn)和零件結(jié)合外加附加增值功能的中心NFT幣。增值可以通過個人花費時間和精力,或者購買來實現(xiàn)。

在奢侈品行業(yè)里,這些可以作為應(yīng)用于不同時尚品牌的“外表”和“包裝”。 比如說,中心的不可替代貨幣是外表,可以輔助鞋子和錢包,每一個都代表了他們自己的NFT。這一整個套裝都作為一部分組合到ERC-998代幣里面。
單一資產(chǎn)的幾個組成部分
作為附加債券的一部分,單一的數(shù)字資產(chǎn)可以被ERC-998代幣群組所代表。因為每一個部分都是由自己的NFT被獨特的體現(xiàn)出來的,NFT代幣組合可以保證貨品的絕對真實性。然而,除非依附于實際商品的形式,每一個NFT都沒有自己的價值。這是一個可以附加在類似手表,珠寶這樣價值商品上的非常強勢的防偽手段。

上圖所示為勞力士的三個組件,每個組件都有一個單獨的序列號 - 表殼、表面和指針。單獨來看,這些部件幾乎沒有任何價值,但它們一起構(gòu)成了一個真正的勞力士手表,由一個ERC-998代幣所代表。
分組集合
通常被認(rèn)為是組合的任何東西,例如一副牌,一本歷史郵票或罕見的硬幣收集等,可以在一個組合型代幣下結(jié)合在一起。因此,完整的組合可以由單個數(shù)字資產(chǎn)表示。
大多數(shù)奢侈品牌都有很大眾的產(chǎn)品,每年都會使用重新設(shè)計的型號,這些產(chǎn)品往往成為收藏品。在奢侈品戰(zhàn)略下,消費者購買經(jīng)典和品牌,這些都是通過多年來產(chǎn)品的演變出來的。作為上圖中的示例,該品牌在三年內(nèi)發(fā)布了其第一、二、三代模型,這些模型被分組為一個組合代幣。
同時,這也更為品牌加強與老客戶的聯(lián)系。例如,如果用戶可以通過Smart-Links這樣可組合的代幣,顯示他們對某個品牌的所有收藏品,那么該品牌將能夠通過獨家邀請和優(yōu)惠來獎勵這位客戶。
4.4 ERC1155
狀態(tài):
草稿(Draft)標(biāo)準(zhǔn)說明:
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md推薦樣例:
ERC-1155是一種定義token的新標(biāo)準(zhǔn),1155是這種方法的編號。1155標(biāo)準(zhǔn)定義了一種解決上述問題的新方法?,F(xiàn)在『物品』(可能包含ERC20的token或ERC721的token或兩者都有)可以被單一的一個合約(打包處理)來定義了。合約里包含區(qū)別token們所需的最小量的數(shù)據(jù)。合約的狀態(tài)包含了每個token ID的配置信息和管理收集的所有行為。ERC-1155的靈活性更強,它使得開發(fā)者可以自行選擇是批量生成某一種特定的token,還是構(gòu)建不可被復(fù)制的惟一元數(shù)據(jù)。
ERC-1155支持原子交換,“原子交換”是指不通過中介物而將一種token換成為另外一種token。
ERC-1155的最大進步就是可以融合不同token(可能是“可替換”的代幣與“不可替換”的代幣的混合體)進行“打包處理”。
函數(shù)接口說明:
name(uint256 _itemId):
symbol(uint256 _itemId):
decimals(uint256 _itemId):
totalSupply(uint256 _itemId):
balanceOf(uint256 _itemId, address _owner):
allowance(uint256 _itemId, address _owner, address _spender):
transfer(uint256[] _itemId, address[] _to, uint256[] _value):
transferFrom(uint256[] _itemId, address[] _from, address[] _to, uint256[] _value):
approve(uint256[] _itemId, address[] _spender, uint256[] _value):
increaseApproval(uint256[] _itemId, address[] _spender, uint256[] _addedValue):
decreaseApproval(uint256[] _itemId, address[] _spender, uint256[] _subtractedValue):
ownerOf(uint256 _itemId):
itemURI(uint256 _itemId):
itemByIndex(uint256 _itemId, uint256 _index):
itemOfOwnerByIndex(uint256 _itemId, address _owner, uint256 _index):
4.5,ERC1190
-
狀態(tài):
還處于pull request下(issue) -
提交記錄:
https://github.com/ethereum/EIPs/issues/1190 - 標(biāo)準(zhǔn)說明:
-
推薦樣例:
ERC1190的token將使每個數(shù)字對象的創(chuàng)建者(如藝術(shù)品或游戲中的物品)在每次使用該對象時會自動受益,無論是下一秒還是幾年之后。
每位ERC1190 token的持證者都可以單獨持有“創(chuàng)造權(quán)”或“所有權(quán)”,當(dāng)然也可以同時持有兩個權(quán)利。
ERC1190的三種獲益方式:
1.銷售“所有權(quán)”;
2.銷售“創(chuàng)造權(quán)”;
3.在固定時間內(nèi)出租“所有權(quán)”。
一個數(shù)字產(chǎn)品的“所有權(quán)”持有者和“創(chuàng)造權(quán)”持有者通過以上三種方式都會自動獲得一定收益。
1. 創(chuàng)造者將擁有“創(chuàng)造權(quán)”和“所有權(quán)”
我們以網(wǎng)絡(luò)游戲中的“裝備”為例。
物品的創(chuàng)建者可以將物品及其所有權(quán)信息嵌入到一個ERC1190 token中。
簡單來說,我在游戲里制造了一把劍并把他命名為“裂魂之劍”。

身為創(chuàng)造者的我就會擁有他的“創(chuàng)造權(quán)”和“所有權(quán)”。
如果我想銷售我的“裂魂之劍”那么它的“所有權(quán)”將會被轉(zhuǎn)交給一個第三方參與者(此處我們將他定為玩家A),但是我還會保留它的“創(chuàng)造權(quán)”。
在這次銷售中,我一次性獲得了“所有權(quán)”帶來的收益,并會在將來的某個時刻獲得一定比例的“所有權(quán)”收益。

2. 如果“所有權(quán)”持有者再次發(fā)生轉(zhuǎn)換,創(chuàng)造者將會獲得收益
擁有“裂魂之劍”“所有權(quán)”的玩家可以永久持有該裝備,在游戲里如果這件裝備得到了更好的優(yōu)化或者其他玩家因為某種原因喜歡上了這件裝備,那么它的價格也必定會有所提高。
當(dāng)玩家A決定銷售“裂魂之劍”的“所有權(quán)”給玩家B時,他會從中獲得高比例的收益,而擁有“創(chuàng)造權(quán)”的我將會獲得低比例的收益。
如:10%。(這個比例會在一開始設(shè)計該token的時候?qū)懺趨f(xié)議上)每一次“所有權(quán)”的轉(zhuǎn)換,“創(chuàng)造權(quán)”持有者都會自動獲得售價10%的收益。

3. 如果“所有權(quán)”持有者出租了“裝備”,那么創(chuàng)造者也可以獲得一定比例的租金
如果玩家B暫時不需要使用“裂魂之劍”。
他便有權(quán)將“裝備”出租給玩家C。按照規(guī)定,做為創(chuàng)造者的我將會獲得租金里的10%,而這個過程也是可以無限循環(huán)的(任何一次有關(guān)“裝備”權(quán)益的轉(zhuǎn)換都需要支付給創(chuàng)造者一定比例的費用)。
其實不單單是在游戲領(lǐng)域,在其它的的虛擬領(lǐng)域都可以進行這一活動,如影音,藝術(shù)等。人們不用再擔(dān)心復(fù)雜的交易流程和版權(quán)費問題了。
規(guī)則被寫入了智能合約,基于區(qū)塊鏈技術(shù),雙方的任何行為都會自動觸發(fā)后續(xù)動作。

4. 創(chuàng)造者銷售“創(chuàng)造權(quán)”
身為創(chuàng)造者的我有權(quán)出售“裂魂之劍”的“創(chuàng)造權(quán)”,并且我將會一次性的拿到所有收益,這其中的收益比銷售“所有權(quán)”所帶來的收益要高得多。
之后,新的“創(chuàng)造權(quán)”持有者在未來的“權(quán)益”轉(zhuǎn)換過程中會重復(fù)上面的步驟,只要他不出售自己的“創(chuàng)造權(quán)”,他將繼續(xù)重復(fù)獲得租金或“所有權(quán)”轉(zhuǎn)換所帶來的收益。

用一個現(xiàn)實世界的例子“房屋”來解釋,你擁有它的房產(chǎn)證并且擁有它的出租權(quán),使用權(quán)。
你作為房產(chǎn)證的擁有者可以將房子的使用權(quán)出售給客人A,而客人A可以選擇將他的使用權(quán)賣給客人B或者將使用權(quán)出租給客人B。
而你依舊可以獲得一定比例的房租收益或售賣分紅,且最終房屋還是歸你所有。
當(dāng)你賣掉了房產(chǎn)證之后才會從這個利益關(guān)系中徹底退出,之后任何的“權(quán)益”轉(zhuǎn)換也就和你沒有半毛錢關(guān)系!
函數(shù)接口:
function approve(address[] owners, uint royaltyForOwnershipTransfer, uint royaltyForRental) returns uint256;
說明:Function to initialize token and set the owner(s) and the royalty rates. Returns the unique token ID for the digital asset.function transferCreativeLicense(address[] creativeLicenseHolders, address[] newOwners, uint256 tokenId);
說明: Function to transfer creative license of token。function transferOwnershipLicense(address[] creativeLicenseHolders, address[] ownershipLicenseHolders, address newOwners[], uint256 tokenId);
說明:Function to transfer ownership license of tokenfunction rentAsset(address[] creativeLicenseHolders, address[] ownershipLicenseHolders, address[] renters, uint256 tokenId);
說明:Function to rent asset
5 STO標(biāo)準(zhǔn)相關(guān)
5.1 ERC1400(ERC1410,ERC1411)
狀態(tài):
草稿(Draft)提交記錄:
1)ERC 1410: Partially Fungible Token Standard:
https://github.com/ethereum/EIPs/issues/1410
2)ERC 1400: Security Token Standard #1411
https://github.com/ethereum/EIPs/issues/1411標(biāo)準(zhǔn)說明
推薦樣例:
https://blog.neufund.org/good-protocols-how-to-properly-standardize-security-tokens-95ff83c81c4a
標(biāo)準(zhǔn)說明
該標(biāo)準(zhǔn)由 Gosselin, Adam Dossa, Pablo Ruiz 和 Fabian Vogelsteller 撰寫。其中 Gosselin 和 Dossa 為 Polymath 工作,而 Ruiz 擁有國際商業(yè)和金融背景,而 Dossa 是以太坊開發(fā)人員和網(wǎng)頁設(shè)計師。團隊經(jīng)驗互補,有一定的實力。
ERC1410 (等同ERC1411)將 ERC20/ERC777 中不存在解釋屬性的余額,附加額外的信息,從而劃分成不同的部分,就可以做一些操作上的限制。
而 ERC1400 (等同ERC1411)是對 ERC1410 標(biāo)準(zhǔn)的繼承和改進。
無論是 ERC20 還是 ERC777,每個單位的 Token 都是相同的,并無附加屬性,屬于 fungible token(同質(zhì)化代幣/可互換 Token)。ERC721標(biāo)準(zhǔn)的 Token,每個 Token 均有不同的ID,不同ID可以有不同的解釋,屬于 no-fungible token(非同質(zhì)化 Token,不可互換 Token)。
ERC1410標(biāo)準(zhǔn)的 Token 屬于Partially-Fungible Token (部分可互換 Token ),將 ERC20/ERC777 中不存在解釋屬性的余額,附加額外的信息,從而劃分成不同的部分,就可以做一些操作上的限制(例如:某些操作只限定于指定 tranche 的 Token,某些操作優(yōu)先消耗指定tranche的 Token)。
ERC1400 則是繼承 ERC1410 標(biāo)準(zhǔn),增加了證券相關(guān)業(yè)務(wù)會使用到的函數(shù):證券增發(fā),相關(guān)法律文件存儲等。
先前一些證券型 Token 的合約大多是在 ERC20 標(biāo)準(zhǔn)的基礎(chǔ)上,通過維護一個或多個以太坊地址集合,對這部分地址做出了劃分:是否通過kyc,是否處于鎖定期等,來進行轉(zhuǎn)賬上的限制。這些都是在地址層面做出不同的解釋。而 ERC1400 對 Token 本身做了不同解釋,以適用于更復(fù)雜的證券相關(guān)業(yè)務(wù)場景。
關(guān)于ERC20,以及其它ERC成員的關(guān)系,可見下圖:

函數(shù)接口說明
/// @title ERC-1410 Partially Fungible Token Standard
/// @dev See https://github.com/SecurityTokenStandard/EIP-Spec
interface IERC1410 is IERC777 {
// Token Information
function balanceOfByTranche(bytes32 _tranche, address _tokenHolder) external view returns (uint256);
function tranchesOf(address _tokenHolder) external view returns (bytes32[]);
// Token Transfers
function sendByTranche(bytes32 _tranche, address _to, uint256 _amount, bytes _data) external returns (bytes32);
function sendByTranches(bytes32[] _tranches, address _to, uint256[] _amounts, bytes _data) external returns (bytes32[]);
function operatorSendByTranche(bytes32 _tranche, address _from, address _to, uint256 _amount, bytes _data, bytes _operatorData) external returns (bytes32);
function operatorSendByTranches(bytes32[] _tranches, address _from, address _to, uint256[] _amounts, bytes _data, bytes _operatorData) external returns (bytes32[]);
// Default Tranche Management
function getDefaultTranches(address _tokenHolder) external view returns (bytes32[]);
function setDefaultTranche(bytes32[] _tranches) external;
// Operators
function defaultOperatorsByTranche(bytes32 _tranche) external view returns (address[]);
function authorizeOperatorByTranche(bytes32 _tranche, address _operator) external;
function revokeOperatorByTranche(bytes32 _tranche, address _operator) external;
function isOperatorForTranche(bytes32 _tranche, address _operator, address _tokenHolder) external view returns (bool);
// Transfer Events
event SentByTranche(
bytes32 indexed fromTranche,
address operator,
address indexed from,
address indexed to,
uint256 amount,
bytes data,
bytes operatorData
);
event ChangedTranche(
bytes32 indexed fromTranche,
bytes32 indexed toTranche,
uint256 amount,
);
// Operator Events
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
event RevokedOperator(address indexed operator, address indexed tokenHolder);
event AuthorizedOperatorByTranche(bytes32 indexed tranche, address indexed operator, address indexed tokenHolder);
event RevokedOperatorByTranche(bytes32 indexed tranche, address indexed operator, address indexed tokenHolder);
}
/// @title IERCST Security Token Standard (EIP 1400)
/// @dev See https://github.com/SecurityTokenStandard/EIP-Spec
interface IERCST is IERCPFT {
// Document Management
function getDocument(bytes32 _name) external view returns (string, bytes32);
function setDocument(bytes32 _name, string _uri, bytes32 _documentHash) external;
// Controller Operation
function isControllable() external view returns (bool);
// Token Issuance
function isIssuable() external view returns (bool);
function issueByTranche(bytes32 _tranche, address _tokenHolder, uint256 _amount, bytes _data) external;
event IssuedByTranche(bytes32 indexed tranche, address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
// Token Redemption
function redeemByTranche(bytes32 _tranche, uint256 _amount, bytes _data) external;
function operatorRedeemByTranche(bytes32 _tranche, address _tokenHolder, uint256 _amount, bytes _operatorData) external;
event RedeemedByTranche(bytes32 indexed tranche, address indexed operator, address indexed from, uint256 amount, bytes operatorData);
// Transfer Validity
function canSend(address _from, address _to, bytes32 _tranche, uint256 _amount, bytes _data) external view returns (byte, bytes32, bytes32);
}
5.2 ERC1404
-
狀態(tài):
草稿(Draft) -
提交記錄:
https://github.com/ethereum/EIPs/issues/1404
ERC-1404是由TokenSoft工程團隊提出的通證標(biāo)準(zhǔn),其設(shè)計目的就是為證券通證、通證化證券以及其它攜帶復(fù)雜要求的其它通證而準(zhǔn)備的。
根據(jù)介紹,ERC-1404具有ERC-20通證標(biāo)準(zhǔn)的所有優(yōu)點,例如,易于部署以及與以太坊網(wǎng)絡(luò)的可互操作性。此外,該標(biāo)準(zhǔn)還提供了一些關(guān)鍵的改進,允許發(fā)行者實施監(jiān)管性轉(zhuǎn)讓限制。
ERC1404在ERC20的基礎(chǔ)上增加2個函數(shù)。
contract ERC1404 is ERC20 {
function detectTransferRestriction (address from, address to, uint256 value) public view returns (uint8);
function messageForTransferRestriction (uint8 restrictionCode) public view returns (string);
}
函數(shù)說明:
detectTransferRestriction:此函數(shù)是發(fā)行者強制執(zhí)行通證傳輸?shù)南拗七壿?。例子包括,?)檢查通證接收者是否在白名單內(nèi),(2)檢查發(fā)送者的通證是否在鎖定期內(nèi)被凍結(jié)等等。該函數(shù)實現(xiàn)僅面向發(fā)行者,另外,第三方可以公開調(diào)用該函數(shù)來檢查轉(zhuǎn)移的預(yù)期結(jié)果。因為這個函數(shù)會返回一個uint8代碼,所以它允許函數(shù)調(diào)用者知道傳輸失敗的原因,并將其報告給相關(guān)的對方。
messageForTransferRestriction:這個函數(shù)實際上是一個“消息”訪問器,它負(fù)責(zé)以人類可閱讀的方式解釋一筆交易為什么會被限制。通過規(guī)范消息查找,開發(fā)者授權(quán)用戶界面構(gòu)建器,有效地向用戶報告錯誤。
5.3 ERC1594
狀態(tài):
草稿(Draft)標(biāo)準(zhǔn)說明:
推薦樣例:
說明文檔
參考《通往STO之路|ERC-1594標(biāo)準(zhǔn)詳解》了解相關(guān)中文翻譯。
6,ERC865
狀態(tài):
還處于pull request下(issue)標(biāo)準(zhǔn)說明:
以太坊開發(fā)者Bhaskar Sharma在Medium網(wǎng)站上發(fā)表了一篇文章,提出了一個在以太坊中使用對用戶更友好的代幣的提案,這一提案將允許用戶來采用去中心化應(yīng)用程序(DApps)時使用代幣(tokens)來支付交易費用,而不是用以太幣ETH來支付。
他認(rèn)為,以太坊區(qū)塊鏈中的費用支付問題為新手帶來了麻煩,這些費用用于支付礦工將交易打包到區(qū)塊并確保區(qū)塊鏈的安全。用戶必須認(rèn)識以太坊的工作原理,這樣才能理解燃料(gas)價格和成本。用戶還需要獲得必要的以太幣來支付這兩種費用。
函數(shù)接口說明:
transferPreSigned(bytes _signature, address _to, uint256 _value, uint256 _gasPrice, uint256 _nonce):
approvePreSigned(bytes _signature, address _spender, uint256 _value, uint256 _gasPrice, uint256 _nonce):
**approveAndCallPreSigned(bytes _signature, address _spender, uint256 _value, bytes _extraData, uint256 _gasPrice, uint256 _nonce) **:
increaseApprovalPreSigned(bytes _signature, address _to, uint256 _amount, uint256 _gasPrice, uint256 _nonce):
decreaseApprovalPreSigned(bytes _signature, address _to, uint256 _amount, uint256 _gasPrice, uint256 _nonce):
revokeSignature(bytes _signature):
7. 其他ERC協(xié)議
7.1 ERC165
-
狀態(tài):
已定稿(Final) -
提交記錄:
https://github.com/ethereum/EIPs/issues/165 -
標(biāo)準(zhǔn)說明:
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
ERC165定義以下功能:
1) 如何識別接口;
2) 一個智能合約如何發(fā)布它執(zhí)行的接口;
3) 如何檢測一個智能合約是否執(zhí)行了ERC-165協(xié)議;
4) 如何檢測一個智能合約是否執(zhí)行了一個給定的接口;