簡(jiǎn)介
本章將深入源碼,為大家分析eos的系統(tǒng)合約eosio.token的實(shí)現(xiàn)細(xì)節(jié)。eosio.token是eos的發(fā)幣合約,這個(gè)合約主要實(shí)現(xiàn)了EOS代幣的創(chuàng)建、發(fā)行、轉(zhuǎn)賬等功能。
主要合約方法
eosio.token系統(tǒng)合約的源碼在eos/contracts/eosio.token中,eos項(xiàng)目方獨(dú)立開了github,負(fù)責(zé)eosio.token合約的更新和維護(hù)。
eosio.token合約,在eosio.token.hpp頭文件中,主要定義了以下三個(gè)合約方法:
- create:負(fù)責(zé)創(chuàng)建資產(chǎn)
- issue:負(fù)責(zé)發(fā)行資產(chǎn)
- transfer:負(fù)責(zé)資產(chǎn)轉(zhuǎn)賬

下面,將為大家一一介紹各個(gè)方法的功能實(shí)現(xiàn)細(xì)節(jié)
create方法
create方法的實(shí)現(xiàn)在eosio.token.cpp中,需要傳入兩個(gè)參數(shù)完成幣種創(chuàng)建:
- issuer:資產(chǎn)發(fā)行賬戶
-?maximum_supply:最大發(fā)行量

ceate方法調(diào)用實(shí)例如下,eosio.token合約部署在eosio.token賬戶,資產(chǎn)發(fā)行賬戶為eosio,最大發(fā)行量10億,幣種精度4,幣種符號(hào)EOS
cleos push action eosio.token create '[ "eosio", "1000000000.0000 EOS"]' -p eosio.token
深入源碼來(lái)看,create方法通過(guò)以下步驟完成了資產(chǎn)的創(chuàng)建:
- 獲取eosio.token合約部署賬戶的授權(quán)
- 判斷幣種符號(hào) (sysmol name) 是否合法,幣種符號(hào)必須是大寫字母,長(zhǎng)度小于8位
-?判斷發(fā)行量是否越界且是否為正數(shù),支持的最大發(fā)行量 amount <=?2^62-1
- 查詢statstable表,判斷代幣符號(hào)是否存在,eosio.token支持發(fā)行多資產(chǎn)
- 建表,將代幣符號(hào)、發(fā)行總量、發(fā)行方存入數(shù)據(jù)庫(kù)
以上步驟,主要邏輯詳見:eos/contracts/eosiolib/symbol.hpp、eos/contracts/eosiolib/asset.hpp、eos/contracts/eosiolib/multi_index.hpp
issue方法
create方法的實(shí)現(xiàn)在eosio.token.cpp中,需要傳入兩個(gè)參數(shù)完成幣種的發(fā)行:
- to:發(fā)行金額打入的賬戶
-?quantity:發(fā)行金額
- memo:交易備注

issue方法調(diào)用實(shí)例如下,資產(chǎn)發(fā)行賬戶eosio授權(quán),將10億EOS打入eosio賬戶中,備注是test issue
cleos push action eosio.token issue '[ "eosio", "1000000000.0000 EOS", "test issue"]' -p eosio
深入源碼來(lái)看,issue方法通過(guò)以下步驟完成了資產(chǎn)的發(fā)行:
- 前置檢查:查表判斷幣種是否存在、memo最大長(zhǎng)度不能超過(guò)256字節(jié)
- 查表獲取幣種信息:發(fā)行賬戶、最大發(fā)行量、幣種精度、幣種符號(hào)
- 獲取發(fā)行賬戶的授權(quán)
- 前置檢查:發(fā)行金額為正數(shù)且不超過(guò)最大發(fā)行量、幣種精度校驗(yàn)
- 更新表,增加發(fā)行資產(chǎn)的余額
- 如果to賬戶和發(fā)行賬戶不一致,調(diào)用內(nèi)聯(lián)合約轉(zhuǎn)賬
以上步驟,主要邏輯詳見:eos/contracts/eosiolib/symbol.hpp、eos/contracts/eosiolib/asset.hpp、eos/contracts/eosiolib/multi_index.hpp、eos/contracts/eosiolib/currency.hpp
這里特別要說(shuō)明最后一個(gè)步驟,內(nèi)聯(lián)合約的調(diào)用。實(shí)現(xiàn)邏輯在eos/contracts/eosiolib/currency.hpp

eos智能合約之間,通過(guò)action通信,共享數(shù)據(jù)庫(kù)存儲(chǔ)。一個(gè)智能合約,可以異步的讀取另一個(gè)智能合約的數(shù)據(jù)庫(kù)狀態(tài)。智能合約有兩種通信狀態(tài):
- Inline 內(nèi)聯(lián)合約。指的是在一個(gè)已有的交易里調(diào)用其他智能合約的方法。如果當(dāng)前交易失敗了,內(nèi)聯(lián)合約的執(zhí)行也不受影響,內(nèi)聯(lián)合約執(zhí)行失敗或成功并沒有通知,但執(zhí)行成功會(huì)上鏈
- Deffered 延遲合約。指的是不是立即執(zhí)行,而是在未來(lái)的某個(gè)時(shí)間計(jì)劃去執(zhí)行的合約。當(dāng)前,可以構(gòu)造一個(gè)交易去發(fā)送延遲合約交易,也可以發(fā)送一個(gè)交易去取消延遲合約。延遲合約也不能保證執(zhí)行成功,執(zhí)行失敗或者成功并沒有通知,但執(zhí)行成功會(huì)上鏈
在issue方法中,當(dāng)發(fā)現(xiàn)issuer賬戶和to賬戶不一致時(shí),會(huì)調(diào)用lnline合約,觸發(fā)eosio.token合約的transfer方法,將發(fā)行的金額轉(zhuǎn)入to賬戶。當(dāng)我們執(zhí)行issue方法后,會(huì)發(fā)現(xiàn)除了產(chǎn)生issue的action后,還會(huì)有transfer的action:

transfer方法
transfer方法的實(shí)現(xiàn)在eosio.token.cpp中,需要傳入四個(gè)參數(shù)完成幣種的轉(zhuǎn)賬:
- from:出幣賬戶
- to:入金賬戶
-?quantity:轉(zhuǎn)賬金額
- memo:交易備注

深入源碼來(lái)看,issue方法通過(guò)以下步驟完成了資產(chǎn)的轉(zhuǎn)賬:
- 前置檢查:判斷是否轉(zhuǎn)賬給自己、判斷to賬戶是否存在
- 獲得from賬戶的授權(quán)
- 獲取幣種信息:發(fā)行賬戶、最大發(fā)行量、幣種精度、幣種符號(hào)
- 分別通知from、to賬戶合約調(diào)用結(jié)果
- 前置檢查:轉(zhuǎn)賬金額為正且不超過(guò)最大發(fā)行量、幣種精度正確、memo長(zhǎng)度不大于256
- 加減from和to地址賬戶余額
以上步驟,主要邏輯詳見:eos/contracts/eosiolib/symbol.hpp、eos/contracts/eosiolib/asset.hpp、eos/contracts/eosiolib/multi_index.hpp、eos/contracts/eosiolib/currency.hpp
這里特別要說(shuō)明第四個(gè)步驟,通知from、to賬戶合約調(diào)用結(jié)果。實(shí)現(xiàn)邏輯在eos/contracts/eosiolib/action.hpp、eos/libraries/chain/apply_context.cpp、eos/libraries/chain/transaction_context.cpp





首先,eosio智能合約的執(zhí)行結(jié)果,會(huì)分別通知from、to、eosio.token。我們發(fā)送轉(zhuǎn)賬交易,會(huì)發(fā)現(xiàn)有三條actions,通知所有涉及的賬戶,這是eos系統(tǒng)合約設(shè)計(jì)的通知機(jī)制。大家在執(zhí)行cleos get actions獲取交易結(jié)果時(shí),可以通過(guò)receiver過(guò)濾出發(fā)給自己賬戶的通知。

receipt的通知詳情,調(diào)用cleos get actions bp1 -j 獲?。?/p>

后記
本章為大家介紹了eosio.token合約的實(shí)現(xiàn)細(xì)節(jié),從源碼層面為大家分析了eosio.token如何實(shí)現(xiàn)資產(chǎn)的創(chuàng)建、發(fā)行、轉(zhuǎn)賬的。
目前,基于eos發(fā)行資產(chǎn)的項(xiàng)目方,都會(huì)參考eosio.token的實(shí)現(xiàn),去實(shí)現(xiàn)自己的發(fā)幣合約。但是,由于eos是一個(gè)剛剛完成主網(wǎng)上線的新項(xiàng)目,有許多隱藏的bug有待發(fā)現(xiàn)。例如,我們最后講到的transfer方法的receipt通知機(jī)制,由于實(shí)現(xiàn)過(guò)于復(fù)雜,前段時(shí)間就被慢霧發(fā)現(xiàn)了有嚴(yán)重的安全漏洞,會(huì)使交易所的提幣賬戶ram被耗盡,詳細(xì)issue。

因此,大家在編寫自己的發(fā)幣合約時(shí),務(wù)必要檢查好相關(guān)邏輯,以免被惡意攻擊造成資產(chǎn)的損失。eos社區(qū)目前還沒有出合約代碼的標(biāo)準(zhǔn)規(guī)范,但我相信不久的將來(lái),一定會(huì)有詳細(xì)的規(guī)范出臺(tái)。
接下來(lái)的文章,將繼續(xù)從源碼層面為大家講解eos的系統(tǒng)合約實(shí)現(xiàn)細(xì)節(jié),盡請(qǐng)期待!