這是區(qū)塊鏈專家K. C. Tam關(guān)于智能合約開發(fā)工具和環(huán)境的詳細(xì)分析與總結(jié)淡溯。通過此文庄岖,相信我們將獲得關(guān)于這些工具的一些深入理解唾戚,對使用Solidity開展智能合約將由非常大的幫助。
首先簡要介紹本文選擇的智能合約走敌。然后在四種環(huán)境中部署此合約匀借。以下是在這里展示的四種環(huán)境的簡要總結(jié)颜阐。
下圖為合約編譯和部署的簡化流程
智能合約范例:收益共享
此應(yīng)用程序摘自A. Bahga和V. Madisetti 的書籍“ 區(qū)塊鏈與應(yīng)用實踐方法 ” 第4章:以太坊帳戶中的智能合約。它已被修改以符合最新版本的Solidity的一些要求吓肋。
這個應(yīng)用程序被稱為收益共享凳怨。簡而言之,部署合約時會給出地址列表蓬坡。任何人都可以發(fā)送一定數(shù)量的資金(這里使用ethers或ethers的面額)猿棉,這筆資金平均分配到清單上的地址磅叛。
一個相當(dāng)簡單的Solidity合約如下:
pragma solidity ^0.4.8;contract RevenueSharing {address public creator;mapping(uint => address) public shareholders;uint public numShareholders;event Disburse(uint _amount, uint _numShareholders);function RevenueSharing(address[] addresses) {creator = msg.sender;numShareholders = addresses.length;for (uint i=0; i< addresses.length; i++) {shareholders[i] = addresses[i];}}function shareRevenue() payable returns (bool success) {uint amount = msg.value / numShareholders;for (uint i=0; i
關(guān)于這份智能合約的簡單說明:
該合約名為RevenueSharing屑咳。
函數(shù)RevenueSharing()與合約本身具有相同的名稱萨赁。它是構(gòu)造函數(shù),并且只在合約部署時調(diào)用一次兆龙。我們在這份合約中看到提供了一系列地址杖爽,這個地址數(shù)組存儲在另一個名為股東的數(shù)組中。
函數(shù)shareRevenue()是此聯(lián)系人中唯一的主要功能紫皇。當(dāng)用一定數(shù)量的ethers(以msg.value)執(zhí)行這個函數(shù)時慰安,金額被分成股東數(shù)量(股東數(shù)量),股東陣列中的每個地址將得到該部分聪铺。我們將在演示中執(zhí)行此功能化焕。
函數(shù)kill()用于刪除合約。我們不會在演示中使用這個功能铃剔。
請注意撒桨,所有變量都是使用public定義的。這有助于我們觀察合約中的更多細(xì)節(jié)键兜。在現(xiàn)實生活中凤类,由于安全考慮,我們在公開變量或功能時應(yīng)該小心普气。
Remix概述
Remix是一套工具谜疤,用于與以太坊區(qū)塊鏈交互以調(diào)試交易(直接引用此處)。有一個IDE版本(Remix IDE)和一個在線版本(如下圖)现诀。
Remix中有很多工具夷磕,但以下工具符合我們的興趣,
? Solidity編譯器仔沿。這會產(chǎn)生很多有用的信息企锌,我們將在另一個環(huán)境中使用
? 運(yùn)行環(huán)境。Remix提供了三種:
? Injected Web3:Mist或MetaMask
? Web3 Provider:通過ipc到本地主機(jī)
? JavaScript VM:一個模擬環(huán)境
在運(yùn)行時環(huán)境中于未,我們使用JavaScript VM撕攒。在JavaScript VM中,Remix附帶五個以太坊帳戶烘浦,每個帳戶都存放100個ethers抖坪。這足以測試我們的智能合約。另外闷叉,由于它是自動完成的擦俐,因此不需要挖掘。
您可以從任何瀏覽器輕松訪問Remix(網(wǎng)址:http://remix.ethereuem.org)握侧。以上是Remix的截圖蚯瞧。
屏幕分為幾個模塊區(qū)域嘿期。
? 智能合約區(qū):我們在此粘貼合約的合約代碼。
? 編譯區(qū)和運(yùn)行區(qū):在編譯標(biāo)簽中埋合,此處顯示任何編譯錯誤或警告备徐。在運(yùn)行標(biāo)簽中,我們部署合約并執(zhí)行合約功能甚颂。
? 事務(wù)日志區(qū):此處可以觀察所有事務(wù)細(xì)節(jié)蜜猾。
編譯合約
我們將智能合約代碼粘貼到Remix中。
我們注意到代碼是自動編譯的振诬,并且有一些警告蹭睡。由于它們不是嚴(yán)重錯誤,因此我們可以繼續(xù)前進(jìn)赶么。
如果我們點(diǎn)擊詳細(xì)信息肩豁,我們會看到很多關(guān)于此合約的信息。其中他們是辫呻,
? 字節(jié)碼
? ABI
? Web3部署
在另一個環(huán)境中部署此合約時需要使用它們清钥,我們稍后會回顧這一點(diǎn)。
由于我們在編譯后看到?jīng)]有錯誤印屁,所以我們可以將此合約運(yùn)行到Remix JavaScript環(huán)境循捺。
部署合約
1.運(yùn)行(Run)一覽
下圖為運(yùn)行菜單界面一覽。
從環(huán)境中選擇JavaScript VM雄人。
選擇JavaScript虛擬機(jī)后从橘,我們會在帳戶字段中看到一些帳戶。
如前所述础钠,每一種都是預(yù)先充入100 ethers用于測試恰力。因為我們稍后會使用這些帳戶,所以我們可以先復(fù)制它們旗吁。
Gas limit是指明我們可以在任何交易中需要多少GAS踩萎。當(dāng)我們處于測試環(huán)境中時,我們并不擔(dān)心這一點(diǎn)很钓。我已經(jīng)嘗試了一些大的合約部署香府,默認(rèn)設(shè)置Gas limit不足(anyway,它可以在需要時調(diào)整到任何值)码倦。
Value 是我們在合約部署和執(zhí)行功能期間發(fā)送ethers的數(shù)量企孩。在我們的案例中,我們沒有在合約部署中放置任何Value袁稽,但是在執(zhí)行該功能時放置了一些ethers勿璃。請參閱下面的更多細(xì)節(jié)。
2.部署合約
現(xiàn)在我們看到已經(jīng)選擇了RevenueSharing合約(我們的代碼中只有一個合約)。我們將使用“創(chuàng)建”按鈕將此合約部署到JavaScript VM上补疑。
需要的東西歧沪,如輸入?yún)^(qū)域中所暗示的:“地址[]地址”,當(dāng)部署合約時莲组。記得這份合約要求將地址列表作為共享目標(biāo)嗎诊胞?為了演示目的,我們將使用上面列出的第3胁编,第4和第5個地址作為地址列表厢钧。因此鳞尔,將其粘貼到創(chuàng)建按鈕旁邊:
現(xiàn)在確保我們已經(jīng)選擇:
? 環(huán)境:JavaScript VM
? 帳戶:部署此合約時的第一個帳戶(以0xca3 ...開頭)
? 將地址數(shù)組粘貼到Create按鈕旁邊
按下Create嬉橙,我們將看到以下情況。
3.合約部署后
該合約現(xiàn)在部署在JavaScript VM(內(nèi)存)中寥假,并顯示合約地址(0x692 ...)市框。我們不在演示中使用此地址。在需要時可以在其他情況下提及該地址糕韧。
此外枫振,我們看到標(biāo)記為“public”的變量現(xiàn)在顯示,它們是萤彩,
? shareholders
? numShareholders
? creator
我們在本合約中定義的兩項功能粪滤,
? shareRevenue()
? Kill()
在此之前,我們觀察到帳戶余額減少了少量的ethers雀扶。差額(417,626 weis杖小,1 wei = 10-18 ether)是部署此合約的成本。在現(xiàn)實生活中愚墓,這是在您部署合約時從您的帳戶中扣除的真正的ethers予权。
與已部署的合約進(jìn)行交互
1.檢查變量
我們可以首先通過按下變量按鈕來檢查變量。在這里我們檢查numShareholder和creator浪册。對股東(shareholders)來說扫腺,因為它是一個數(shù)組,所以我們需要指定一個索引(0,1或2)村象,對應(yīng)于我們在部署(創(chuàng)建)合約時放置的地址笆环。
所有的變量都是我們所期望的。
2.執(zhí)行shareRevenue()函數(shù)
現(xiàn)在我們執(zhí)行shareRevenue()厚者。在執(zhí)行此功能時躁劣,我們使用第一個帳戶來存放30個ethers(這僅用于此功能,在很多情況下這不是必需的)籍救。根據(jù)契約邏輯习绢,30個ethers將被分配到賬戶列表中,即我們賬戶列表中的第3,第4和第5個賬戶闪萄。截至目前梧却,他們每個人的余額仍然是100個ethers。
我們使用相同的地方來執(zhí)行該功能败去。在這里我們確保放航,
? 在帳戶字段中,選擇第一個帳戶(以0xca3 ...開頭)
? 在價值中放置30個ethers
然后按shareRevenue圆裕。
函數(shù)執(zhí)行后广鳍,我們檢查每個帳戶的余額,并根據(jù)我們的設(shè)計查看它是否被執(zhí)行吓妆。
首先赊时,我們看到30個ethers被從第1個帳戶中扣除,并且名單上的所有三個帳戶現(xiàn)在都有110個ethers行拢。因此祖秒,從第一個賬戶中扣除的30個賬戶現(xiàn)在分配到這三個賬戶中。該部分按照合約進(jìn)行完善舟奠。
另外竭缝,如果我們仔細(xì)檢查第一個帳戶的余額,則會扣除一些額外的ethers沼瘫。差額為47,776 wei抬纸,這是此次交易的成本。每筆交易耿戚,功能的執(zhí)行或合約的部署都需要花費(fèi)一定數(shù)量的ethers湿故。
事務(wù)日志
我們在測試過程中沒有碰到事務(wù)日志,但是一切都保存在日志中溅话,甚至是變量的查詢晓锻。讓我們來看看兩個選定日志的細(xì)節(jié)。
1.合約部署
我們可以看到誰已經(jīng)部署了此合約飞几,合約地址以及部署它所需的交易成本砚哆。
2.執(zhí)行shareRevenue()函數(shù)
我們再次將其視為交易成本。在shareRevenue()中屑墨,有一個返回 boolean值躁锁,我們看到“ecoded out”有一個“True”返回。此外卵史,我們有一個成功發(fā)行的動作(我們在“LOG”中可以看到它)
總結(jié):
這就是Remix如何幫助測試我們開發(fā)的代碼战转。它具有非常方便的功能和直觀的用戶界面。在下一篇文章中以躯,我們將使用另一個環(huán)境testrpc來處理同一個合約并了解它是如何工作的槐秧。
用于智能合約開發(fā)的最佳工具第2部分:關(guān)于TestRPC的Web3
概述
TestRPC是以太坊區(qū)塊鏈的模擬啄踊,它帶有10個預(yù)定義的以太坊帳戶并支持助記符(即,可以使用相同的一組助記符生成相同的帳戶集合)刁标。它沒有帶有用戶界面作為Remix颠通,我們需要節(jié)點(diǎn)控制臺加上web3庫來與這個區(qū)塊鏈進(jìn)行交互。
前期準(zhǔn)備
演示通過命令行或終端完成膀懈。使用支持屏幕分割的終端工具顿锰。我在我的Mac上使用iTerm2。
安裝節(jié)點(diǎn)和npm:請參考此處在您的平臺上進(jìn)行安裝启搂。
備注:我最近發(fā)現(xiàn)用npm安裝web3時硼控,安裝了1.0.0 beta版本,之前使用的命令(基于0.20.4)不起作用胳赌。因此我們改為指定web3的版本牢撼。
以下所有命令都在版本0.20.0中。
打開一個終端并將屏幕分成兩部分匈织。左側(cè)是節(jié)點(diǎn)控制臺浪默,我們將在那里工作大部分時間牡直。右側(cè)是我們運(yùn)行TestRPC的地方缀匕。
啟動TestRPC
在右側(cè),啟動TestRPC
這里我們可以看到:
? TestRPC是一個節(jié)點(diǎn)應(yīng)用程序碰逸,模擬內(nèi)存中的以太坊區(qū)塊鏈乡小。
? 10個帳戶是預(yù)先定義的。
? 這些帳戶是通過助記符生成的饵史,每次啟動TestRPC時都不相同满钟。為了保持同一組帳戶,我們可以在運(yùn)行TestRPC時使用上面顯示的助記符作為參數(shù)胳喷。
? 此外湃番,RPC在localhost:8545上打開。Web3正在通過此訪問區(qū)塊鏈吭露。
我們不會再觸及這一部分吠撮,假設(shè)在以太坊區(qū)塊鏈中一切正常〗哺停現(xiàn)在我們更關(guān)注節(jié)點(diǎn)控制臺(左側(cè))泥兰。在測試過程中,我們不斷看到命令和日志發(fā)布到TestRPC端顯示的區(qū)塊鏈题禀。
Web3對象
我們需要指示節(jié)點(diǎn)控制臺鞋诗,我們正在使用web3并指向區(qū)塊鏈web3進(jìn)行連接。
這正是TestRPC中創(chuàng)建的帳戶迈嘹。
顯示余額的方便功能
我找到了一個方便的功能(鏈接)削彬,可以顯示所有帳戶的余額。
只需將此功能復(fù)制粘貼到節(jié)點(diǎn)控制臺即可。現(xiàn)在我們可以隨時調(diào)用函數(shù)checkAllBalances()融痛,并且它會以ether的形式顯示所有賬戶的余額糕篇。請注意,在我們退出節(jié)點(diǎn)控制臺后酌心,此功能將消失拌消,但我們可以隨時將其添加回去。
部署合約
1.編譯合約
現(xiàn)在一切都準(zhǔn)備好了安券。我們可以部署我們的收益分享合約墩崩。
我們需要重新打開Remix,因為我們正在利用Remix上的編譯器侯勉。在我們將合約代碼粘貼到Remix后鹦筹,它會自動編譯。這里我們使用的是合約部署的結(jié)果址貌。
單擊編譯標(biāo)簽上的詳細(xì)信息铐拐,那里有很多信息。
在這些信息中练对,有三個是我們感興趣的:字節(jié)碼遍蟋,ABI和Web3Deploy
字節(jié)碼是編譯后的合約的二進(jìn)制版本,以及要在以太坊虛擬機(jī)(EVM)中運(yùn)行的指令集螟凭,ABI(應(yīng)用程序二進(jìn)制接口)是我們與合約字節(jié)碼交互的接口虚青。
Remix足以準(zhǔn)備Web3Deploy中的代碼,其中字節(jié)碼和ABI已包含在命令中螺男。因此我們只需要使用Web3Deploy部分棒厘。
2.部署合約
首先,根據(jù)合約的要求下隧,我們需要定義一個目標(biāo)賬戶列表奢人。為了演示目的,使用從第二個帳戶開始的三個帳戶淆院,即從eth.accounts [1]到eth.accounts [3]何乎。
然后我們按照Web3Deploy的建議。
根據(jù)ABI創(chuàng)建一個收入分成合約類迫筑。只需從Web3Deploy復(fù)制該行即可宪赶。
node console> var revenuesharingContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"creator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"numShareholders","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"shareholders","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"shareRevenue","outputs":[{"name":"success","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"inputs":[{"name":"addresses","type":"address[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_amount","type":"uint256"},{"indexed":false,"name":"_numShareholders","type":"uint256"}],"name":"Disburse","type":"event"}]);
現(xiàn)在用字節(jié)碼來部署契約,加上必要的信息脯燃。再次搂妻,我們可以從Web3Deploy復(fù)制該行。已部署的合約是一個名為收益共享的對象辕棚。
node console> var revenuesharing = revenuesharingContract.new(addresses,{from: web3.eth.accounts[0], data: '0x6060604052341561000f57600080fd5b60405161049d38038061049d833981016040528080518201919050506000336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508151600281905550600090505b81518110156100f957818181518110151561009157fe5b906020019060200201516001600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808060010191505061007a565b50506103938061010a6000396000f30060606040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806302d05d3f1461007257806341c0e1b5146100c757806368eca613146100dc578063ab377daa14610105578063e579a0bd14610168575b600080fd5b341561007d57600080fd5b61008561018a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100d257600080fd5b6100da6101af565b005b34156100e757600080fd5b6100ef610240565b6040518082815260200191505060405180910390f35b341561011057600080fd5b6101266004808035906020019091905050610246565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610170610279565b604051808215151515815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561023e576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b565b60025481565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060006002543481151561028b57fe5b049150600090505b60025481101561031d576001600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050151561031057600080fd5b8080600101915050610293565b7f9c26340b8d01b4e039192edfd25f4a56ed070d45afe866b8685658b1ed3cd74d34600254604051808381526020018281526020019250505060405180910390a1600192505050905600a165627a7a72305820f0e717ba935e00c43896cc9266a85af91a519061c044503be0a52b93f721d1610029', gas: '4700000'}, function (e, contract){console.log(e, contract);if (typeof contract.address !== 'undefined') {console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);}})
我們將會(幾乎立即)看到合約已經(jīng)開采欲主。
現(xiàn)在我們可以使用對象收益共享與此已部署的合約進(jìn)行交互邓厕。
與已部署的合約進(jìn)行交互
已部署的合約通過對象收益共享進(jìn)行訪問。
1.檢查公共變量
我們可以檢查那些標(biāo)記為“公開”的變量扁瓢。
2.執(zhí)行shareRevenue()函數(shù)
在我們執(zhí)行shareRevenue()函數(shù)之前详恼,讓我們看看余額。
請注意引几,某些金額在已部署合約的帳戶[0]中扣除昧互。為部署付費(fèi)的ethers數(shù)量為417,626枚。當(dāng)我們在Remix中這樣做時伟桅,您可以檢查它是確切的交易成本敞掘。
現(xiàn)在我們執(zhí)行該功能。
node console> revenuesharing.shareRevenue({from: web3.eth.accounts[0], value: web3.toWei(30), gas: 4700000});
在這里楣铁,我們調(diào)用函數(shù)shareRevenue()玖雁,并指定它由賬戶[0]執(zhí)行,其中30個ethers(wei是web3中的函數(shù)盖腕,用于將30個ethers轉(zhuǎn)換為wei赫冬,因為wei是命令中接受的單位)。我們還把我們允許花費(fèi)的氣體(這是超過要求的方式溃列,但執(zhí)行后我們會得到退款)劲厌。
交易執(zhí)行后,我們可以再次查看余額哭廉。
我們已經(jīng)實現(xiàn)了我們所預(yù)期的目的:從賬戶[0]中扣除30個賬戶并分配到賬戶[1]到賬戶[3](現(xiàn)在每個賬戶都有110個賬戶)脊僚。除此之外,還有一部分金額用于執(zhí)行此次交易遵绰。它仍然是47,776 weis,與我們在Remix中觀察到的相匹配增淹。
總結(jié)
我們已經(jīng)在TestRPC上成功完成了同樣的任務(wù)椿访。除了我們必須在節(jié)點(diǎn)控制臺和web3上與TestRPC中的區(qū)塊鏈進(jìn)行交互之外,整體流程與Remix中的流程幾乎相同虑润。
來源:微信公眾號:區(qū)塊鏈大小姐