Ethereum ERC20 Token Standard 以太坊代幣標準介紹

ERC20: The Ethereum Token Standard (ETHNews)

當今虛擬貨幣界的第二把交椅便是 Ethereum(ETH) ,價格從 2017 年初的 1 顆 10 USD 到 2018 年初的 1000 USD,以百倍的漲幅為人所知。以太坊另一特點便是智能合約功能,其中最知名的應用便是使用智能合約實做出 Token 代幣,來做為價值傳遞媒介使用,知名的代幣例子有 EOSQtum (QTM)OmiseGO (OMG) 等等,詳細請參考 Token List

在 Ethereum 上實作 Token 是一件稍微有點門檻的事情,這篇文章的目標就是解說何謂 ERC20 Token Standard,以供實作參考。

在開始之前先讓我來回答 5 個常見的 Token 相關問題:

1. Ethereum Token 是一種虛擬貨幣嗎?
虛擬貨幣的定義因人而異,我會比較傾向說 Token 是一種以太坊代幣,而符合 ERC20 的 Token 同樣與各種虛擬貨幣一樣可以當作價值傳遞的媒介,具備轉移或是儲存的機制,使用的方式上,與一般的貨幣是極為類似的。

2. 為什麼 Token 需要有 ERC20 ?
Token 只是以太坊智能合約的一種應用,可以想像這種代幣只是存在於某個智能合約中的紀錄,這個合約上記載著每個以太坊地址擁有的 Token 數量多寡,而每次的轉移都是呼叫原本創建 Token 合約裡面的 Function 去做改動,亦即人們可以在創建 Token 時,可以自由訂定規則,像是我可以制定一種完全無法轉移的 Token,但這樣的設計, Token 就變得沒有價值傳遞的意義存在,因此為了要讓代幣能擁有合理的貨幣機制,才會有 ERC20 被設立。往後我們只要知道,若是一個 Token 符合 ERC20,即代表他是一種具有完整貨幣交易功能的代幣。

3. BTC、ETH、LTC 都有自己的錢包,ERC20 的 Token 有自己的錢包嗎?
沒有。因為 ERC20 的代幣,只是存在於智能合約上的一個數值,可以想像成有一張合約上面記載著某個以太坊地址有多少該 Token 的存在,換句話說,所有的 ERC20 Token 都透過普通的 ETH 錢包地址就可以管理。

4. 要用什麼語言來撰寫 Ethereum 智能合約呢?
Solidity。實際上,撰寫以太坊智能合約的語言不只一種,有各種支援智能合約的語言,它們的 Compiler 會將程式碼轉換成 Bytecode 提供給區塊鏈讀取,但目前最主流的即為 Solidity,網路上相關資源最豐富,擁有類似 JavaScript 的語法,有 JavaScript 基礎的人可以無痛上手,詳細可參考 Document

5. ERC20 的規則究竟在哪裡,可以告訴我嗎?

https://theethereum.wiki/w/index.php/ERC20_Token_Standard

結束了常見問題後,就讓我們進入 ERC20 Token Standard 的解說:

一開始的 Interface 定義了 ERC20 需擁有的 6 個 Function 和 2 個 Event,此處僅用以表示該 Function 的 Input 格式和 Output 格式,以及 Event 的 Input 格式,不會描述相關的內容與細節。

其中 Event 僅做為紀錄使用,並不會影響整體智能合約的運作,通常是用來為重要的事件留紀錄,例如 Token 的轉移等紀錄,而平常 Web 上的應用,能直接透過讀寫 Event 來了解該合約發生過的 Log 紀錄,詳細可以參考這篇,而關於這 6 個 Function 的介紹會在文章後面做詳細介紹。

查看上面的程式碼,可以發現有些 Function 後方標示了 constant,這表示該 Function 並不會更改智能合約上的 State,僅以唯獨的方式讀取,讀取這種 Function 不需要花費 Gas ,而可以免費的被查看,換言之,若是有任何 Function 會更動到 智能合約的 State,則其必然需要支付礦工費,讓礦工幫你執行與驗證此筆更動智能合約的 Transaction。

ERC20 需要設定此 Token 的三個資訊: name、symbol、decimals

  • name 是指此 Token 的名字。
  • symbol 則是此 Token 會使用的代稱,像是 Cobinhood Token 的 symbol 就是 COB,而此 symbol 也會出現在 Etherscan 上面,讓人可以一目了然,此範例則是設定成 SYM。
  • decimals 是用來設定此 Token 最小會有幾個位數,通常會設定成 18,意即最多到達小數點後 18 位數,這樣的設定跟 Ether 本身的設定也是一樣的。

補充說明:在 Solidity 中並沒有浮點數的存在,所有的運算都是整數,因此平常我們所說的 1 Ether,事實上在 Solidity 程式中是以 10¹⁸ 來撰寫,最直覺的想像就是我們平常所說的 Ether 或是 Token 數值,當拿到 Solidity 裡面時就需要乘以 10¹⁸ 才是正確的方式。

接下來讓我們看看 ERC20 中的 Function 是如何定義與撰寫的:

  • mapping(address => uint256) balances 用來定義了一個名為 balances 的 Mapping,而此 Mapping 就是用以儲存每個地址對應的 Token 數量,我們可以想像記錄「A 地址上對應了 100 顆 Token」,而若我要查詢 A 地址有多少 Token,只要來此合約上查看一下這個 Mapping 就能找到數量,就是這麼單純的紀錄方式。
  • mapping(address => mapping (address => uint256)) allowed 則看起來複雜許多,但其實就只是兩層的 Mapping,用來紀錄某個地址允許另一個地址動用多少的 Token,較常見的應用就是讓其他智能合約來使用此 Token 做事,假設我們的錢包地址為 B 地址,若是今天有另一個智能合約其合約地址為 C ,合約 C 會透過支付 SYM Token 的方式來做某些動作,由於在 ERC20 的設計下,每個地址僅能操作屬於自己的 Token,因此合約 C 就無法直接使用 B 地址所擁有的 Token,這個時候 allowed Mapping 就顯得有用,因為它上面可以記錄一個允許操作值,像是「B 錢包地址允許 C 合約地址動用屬於 B 錢包地址的 1000 SYM Token」,以 Mapping 的結構來說便記為「B => C => 1000」
  • balanceOf(address tokenOwner) 僅是一個 Function,呼叫它則會得到該傳入地址相對應的 Token 數量
  • transfer(address to, uint tokens) 會將 msg.sender (msg.sender 為保留字,意指呼叫此 Function 的 Address)的 Token 按照 Input 的數量轉移給 Input 的地址,完成轉移後,會使用 Transfer(msg.sender, to, tokens) 呼叫 Event Transfer 來留作 Log
  • transferFrom(address from, address to, uint tokens) 比較複雜一點,首先先將 msg.sender 的 balance 扣除 Input 的 Token 量,接下來將 allowed[from][msg.sender] 扣除 Input 的 Token 量,用意是要將原先 msg.sender 允許 address from 操控的 Token 額度扣掉,最後再將該數量的 Token 轉移到 address to 上面
  • function approve(address spender, uint tokens) 便是我們用來增加 allowed 的 Function,在此設定 address spender 可操控 msg.sender 的 Token 數量,結束時則使用 Approval(msg.sender, spender, tokens) 呼叫 Event Approval 來留作 Log

接著來看幾個比較實際的例子,參考自官方Document:

Token Balance
我們假設這個智能合約目前有兩個地址擁有該 Token (錢包地址僅供參考)
balances[0x1111111111] = 100
balances[0x2222222222] = 200
則 Function balanceOf 則會回傳以下資訊:
tokenContract.balanceOf(0x1111111111) will return 100
tokenContract.balanceOf(0x2222222222) will return 200
Transfer Token Balance
如果 0x1111111111想要轉移 10 tokens 給 0x2222222222,則呼叫
tokenContract.transfer(0x2222222222, 10)
將得到下列結果
balances[0x1111111111] = 90
balances[0x2222222222] = 210
Approve And TransferFrom Token Balance
如果 0x1111111111 允許 0x2222222222 擁有轉移 30 tokens 的權利,則呼叫
tokenContract.approve(0x2222222222, 30)
將得到下列結果
tokenContract.allowed[0x1111111111][0x2222222222] = 30
如果此時 0x2222222222 想要轉移 0x1111111111 的 20 tokens 給自己,則呼叫
tokenContract.transferFrom(0x1111111111, 0x2222222222, 20)
將得到下列結果
tokenContract.balances[0x1111111111] = 70
tokenContract.balances[0x2222222222] = 230
tokenContract.allowed[0x1111111111][0x2222222222] = 10

以上就是關於 ERC20 的說明,只要智能合約所撰寫的 Token 有符合上述的所有機制,便可以被視為是符合 ERC20 ,能在支援的錢包內顯示餘額以及操作(如 imToken、MyEtherWallet),下一篇我將會實際說明一個符合 ERC20 的 Token ,也同時會講解如何實作 ICO( Initial Coin Offering) 智能合約機制。

我們下次見!