在本文中,咱們將討論經過RSK
網絡部署和交互Smart-Contracts
智能合約。咱們的合約將是一個基於OpenZeppelin庫的ERC20代幣,咱們將把它直接部署到Mainnet中。php
咱們須要作的第一件事就是知道如何使用Truffle
。java
當咱們這樣作node
$ truffle init
在一個空文件夾中,除了建立配置文件外,咱們還爲項目和遷移合約建立了文件夾,以記錄對同一合約的更改。python
合約的.sol
代碼文件位於android
~/Truffle/contracts
遷移腳本在git
~/Truffle/migrations
已編譯的合約在程序員
~/Truffle/build
測試合約在github
~/Truffle/test
咱們如今只處理前兩個文件夾。web
在Truffle文件夾中,咱們從OpenZeppelin導入庫mongodb
$ npm install -E openzeppelin-solidity
這些庫不只會安裝咱們代幣token的主要類庫,還會安裝全部權相關,安全數學運算和許多其餘設施的庫。值得一提的是,這些庫已通過審覈以實現高標準的安全性,所以依賴於它們的合約在正確使用時不易受到黑客攻擊。
咱們的庫將安裝在
~/Truffle/node_modules/openzeppelin-solidity/contracts
以後,咱們能夠將庫ABCD.sol
導入到咱們的合約中,以下所示:
import 'zeppelin-solidity/contracts/token/ERC20/ABCD.sol';
要建立咱們的ERC20代幣,咱們將從該存儲庫導入2個庫:StandardToken.sol
,它具備代幣的主要功能,而且已經更多地導入了一堆庫,例如SafeMath.sol
;Ownable.sol
,這些容許咱們設置全部者對合約中的功能控制。
要繼承庫屬性和函數,咱們只需使用「is」關鍵字以這種方式將合約定義爲StandardToken
和Ownable
:
contract CoinFabrikToken is StandardToken, Ownable { }
以後,咱們擁有這些庫和導入庫中的全部功能。
接下來,咱們將代幣的名稱定義爲CoinFabrik
,這是它的符號,18個小數位,用於代幣的精度(以太坊類網絡中的標準,使咱們有可能使用web3的以太轉換功能)並將代幣的初始供應量設置爲1000,像這樣:
string public name = 'CoinFabrik'; string public symbol = 'CF'; uint8 public decimals = 18; uint public INITIAL_SUPPLY = 1000;
咱們還將建立另外一個字符串,一個與代幣功能無關的非公共變量,以顯示Ownable
庫屬性的用法,該屬性僅容許建立者與某些指定的函數進行交互。咱們稍後會看到。
已經定義了咱們的參數,如今是時候經過構造函數將它們分配給Token變量了。到目前爲止,構造函數被定義爲一個與智能合約同名的函數,可是從如今開始,將會有一個名爲constructor()
的函數,它將替換舊方法。若是你像之前同樣調用構造函數,Solidity編譯器將發出警告。
INITIAL_SUPPLY
乘以小數精度的次方將分配給BasicToken
合約的totalSupply_
:
totalSupply_ = INITIAL_SUPPLY * (10**uint(decimals));
並將它們存入創做者的賬戶:
balancesb [msg.sender] = totalSupply_;
有了這個,咱們就可使用一個簡單而標準的代幣,但正如咱們所說,咱們將使用Ownable
合約添加一些功能。首先,咱們將定義一些函數:一個修改咱們的非公共變量的狀態,但只有你擁有權限,而另外一個函數返回字符串的消息。定義以下:
function setON(string _n) public onlyOwner returns (bool) { Owner = _n; return true; } function getON() public view returns (string) { return Owner; }
二者都是公開的,因此任何人均可以嘗試調用他們,但對於第一個,只有全部者的地址不會致使恢復。若是你是全部者而且調用了函數,則字符串將保存在咱們的變量Owner
(帶有大寫字母)中,而且它還將返回一個咱們能夠在交易中檢查的true值。
因爲Owner
變量不是公共的而且沒有Getter,咱們須要一個函數來返回變量的值而不改變區塊鏈的狀態。這是第二個功能。
咱們還將建立一個回調函數,若是有人錯誤地調用咱們的合約,則會發出事件:
function () public payable { if (msg.value > 0) { emit Yes('Thanks for donating SBTC! :)'); } else { emit No('Error 404: Function not found :P'); } }
最後,咱們在合約中添加了一個可銷燬的功能,其中全部者是惟一能夠執行它的人。
咱們的簡單代幣已經完成。全部代碼應該是同樣的:
pragma solidity ^0.4.17; import 'zeppelin-solidity/contracts/token/ERC20/StandardToken.sol'; import "zeppelin-solidity/contracts/ownership/Ownable.sol"; contract CoinFabrikToken is StandardToken, Ownable { string public name = 'CoinFabrik'; string public symbol = 'CF'; uint8 public decimals = 18; uint public INITIAL_SUPPLY = 1000; string Owner; event Yes(string); event No(string); constructor() public { totalSupply_ = INITIAL_SUPPLY * (10**uint(decimals)); balances[msg.sender] = totalSupply_; } function setON(string _n) public onlyOwner returns (bool) { Owner = _n; return true; } function getON() public view returns (string) { return Owner; } function () public payable { if (msg.value > 0) { emit Yes('Thanks for donating SBTC! :)'); } else { emit No('Error 404: Function not found :P'); } } function destroy() public onlyOwner { selfdestruct(owner); } }
對於每一個合約,咱們須要告訴Truffle哪一個合約是咱們想要部署的合約以及咱們能夠在哪裏找到合約。這是經過/Truffle/migrations
文件夾中的遷移文件完成的。
遷移腳本02_deploy_token.js
應以下所示
var CoinFabrikToken = artifacts.require("./CoinFabrikToken.sol"); module.exports = function(deployer) { deployer.deploy(CoinFabrikToken); };
咱們已配置Truffle,咱們的節點已同步,咱們的合約已經編寫而且咱們的遷移已配置,完成部署就是個時間問題。
若是咱們以前中止了咱們的節點,咱們將恢復在線狀態,而後咱們將與Truffle鏈接:
$ sudo service rsk start $ cd ~/Truffle/ && truffle console --network rsk
以後編譯合約:
truffle(rsk)> compile --all
不該該對咱們的合約有任何錯誤或警告。而後咱們轉移合約:
truffle(rsk)> migrate --reset
爲了節約時間,咱們能夠在一行中執行兩個命令
truffle(rsk)> migrate --all --reset
將首先部署遷移合約。Truffle爲咱們提供了每一個操做的交易哈希,所以咱們能夠稍後檢查詳細信息或日誌。這是我收到的完整輸出
truffle(rsk)> migrate --all --reset Compiling ./contracts/CoinFabrikToken.sol... Compiling ./contracts/Migrations.sol... Compiling zeppelin-solidity/contracts/math/SafeMath.sol... Compiling zeppelin-solidity/contracts/ownership/Ownable.sol... Compiling zeppelin-solidity/contracts/token/ERC20/BasicToken.sol... Compiling zeppelin-solidity/contracts/token/ERC20/ERC20.sol... Compiling zeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol... Compiling zeppelin-solidity/contracts/token/ERC20/StandardToken.sol... Writing artifacts to ./build/contracts Using network 'rsk'. Running migration: 1_initial_migration.js Deploying Migrations... ... 0xf00d4ecf2b5752022384f7609fe991aa72dda00a0167a974e8c69864844ae270 Migrations: 0x1dc2550023bc8858a7e5521292356a3d42cdcbe9 Saving successful migration to network... ... 0x3e759e8ff8a7b8e47a441481fa5573ccf502b83f3d591ad3047e622af0f9169e Saving artifacts... Running migration: 2_deploy_token.js Deploying CoinFabrikToken... ... 0x300c8bb1e434e2aa4b13dcc76087d42fcbe0cb953989ca53a336c59298716433 CoinFabrikToken: 0xc341678c01bcffa4f7362b2fceb23fbfd33373ea Saving successful migration to network... ... 0x71771f7ee5d4e251e386979122bdda8728fa519d95a054572751bb10d40eb8c5 Saving artifacts...
若是咱們檢查交易,咱們能夠計算全部部署過程的gas成本。在我這裏的狀況,它是2340788gas(277462+42008+1994310+27008)。
所以將其更改成真實的SBTC,咱們獲得2340788*183000000/10^18=0,000428364 SBTC。在撰寫本文時,這大約是4美圓左右。
咱們的合約如今部署在0xc341678c01bcffa4f7362b2fceb23fbfd33373ea。
恭喜!
經過Truffle遷移給出的地址,以及合約的ABI,咱們建立了一個實例,所以簡化語法更容易處理函數。爲此,在咱們部署以後,咱們寫了
truffle(rsk)> var cfToken = web3.eth.contract(CoinFabrikToken.abi).at(CoinFabrikToken.address)
若是合約已經部署,而且知道它的地址和ABI,咱們就能夠作到
truffle(rsk)> var cfToken = web3.eth.contract(‘Contract_ABI’).at(‘Contract_ADDRESS’)
其中Contract_ABI
是簡化爲一行ABI,Contract_ADDRESS
不須要解釋。
我以前建立了2個賬戶,如今爲方便起見,咱們將它們重命名:
truffle(rsk)> var acc0 = web3.eth.accounts[0] truffle(rsk)> var acc1 = web3.eth.accounts[1]
acc0
是部署合約的人。Acc0
被添加到truffle.js
和node.conf
配置文件中。
咱們將首先使用咱們討論過的庫來測試合約的全部權功能。
若是咱們從任何賬戶調用getON
函數,只要它是公開的而且沒有任何全部權問題,咱們就會獲得:
truffle(rsk)> cfToken.getON() ''
如今,setON函數具備全部權屬性。任何來自其餘賬戶的交易都將被駁回。例如,咱們看到,試圖用個人名字從acc1
簽定合約不會改變它的價值。
truffle(rsk)> cfToken.setON('Andres Bachfischer', {from: acc1}) 0x5f115190b60238240bedf36d1c5bb69a443a0f8ee971b0fc40fe5ca9c727d47c
使用交易的哈希,咱們看到返回的值爲false,而且函數未正確執行。再次調用getON函數,咱們看到變量沒有改變它的值。
如今簽署相同的交易可是從全部者的賬戶acc0,咱們獲得狀態'0x01'而且該功能正確執行。
truffle(rsk)> cfToken.setON('Andres Bachfischer', {from: acc0}) 0x0c894fa7e5369573fb14addeaed4cd9d5b6cd1425cb4eeeae16cb4e1fa8e0364
再次調用函數getON
,咱們看到全部權庫按照咱們但願的那樣工做。
truffle(rsk)> cfToken.getON()
Ownable.sol
還具備容許咱們將合約全部者更改成其餘地址的功能。咱們不會用它。然而,它的用法以下:
truffle(rsk)> cfToken.transferOwnership(acc1, {from: acc0})
有了這個,acc1將成爲合約的新全部者。
讓咱們轉到代幣。
咱們要作的第一件事是檢查在建立合約時是否正確分配了代幣的餘額。
咱們檢查每一個賬戶的餘額以下:
web3.fromWei(cfToken.balanceOf(acc0).toString(10)) // = ‘1000’ web3.fromWei(cfToken.balanceOf(acc1).toString(10)) // = ‘0’
所以,咱們能夠看到全部代幣都已正確分配到咱們的初始賬戶。
咱們要作的第一筆交易是將一些代幣轉移到第二個賬戶acc1
,進行三次。
爲第一筆交易這樣作:
truffle(rsk)> cfToken.transfer(acc1, web3.toWei(88.8), {from: acc0}) 0xd45437b777f1430e7cec57bd80b261ce8f87bf8a3f9a113fecd20563403c4d9c
truffle(rsk)> web3.fromWei(cfToken.balanceOf(acc0).toString(10)) // = '733.6' truffle(rsk)> web3.fromWei(cfToken.balanceOf(acc1).toString(10)) // = '266.4'
咱們看到從咱們的部署賬戶中獲取的代幣與在acc1中收到的代幣數量相同。
使用StandardToken
合約,咱們還得到了表明某個賬戶(在本例中爲acc1)支出代幣的權限。若是咱們想在得到批准以前執行此操做,則交易將失敗(狀態爲「0x00」)
truffle(rsk)> cfToken.transferFrom(acc1, acc0, web3.toWei(5), {from: acc0}) 0x5cee7cf60849283a0088d71483a606ba2101b500e13f972abada4f75781596bf
檢查後,acc0
不容許從acc1
發送:
truffle(rsk)> web3.fromWei(cfToken.allowance(acc1, acc0, {from: acc0}).toString(10)) // = '0'
咱們受權acc0
從acc1
的交易中以acc1
的名義花費10個代幣:
truffle(rsk)> cfToken.approve(acc0, web3.toWei(10), {from: acc1}) 0x6e1a202f4ca7f43dfb28034952d54a572993b986a55857790aa51854afbc1fb4
在輸出日誌中,咱們看到函數已成功完成,而且日誌顯示容許acc0
用於支出的金額。檢查allowance:
truffle(rsk)> web3.fromWei(cfToken.allowance(acc1, acc0, {from: acc0}).toString(10)) // = '10'
如今,若是咱們再次執行支出交易:
truffle(rsk)> cfToken.transferFrom(acc1, acc0, web3.toWei(5), {from: acc0}) 0x41f750eabb6e0d3ab576aac0333b0d337ca61808aae1eeafa9d8e2a0b81b979b
咱們獲得狀態爲「0x01」的成功交易。
再檢查一下餘額:
truffle(rsk)> web3.fromWei(cfToken.balanceOf(acc0).toString(10)) // = '738.6' truffle(rsk)> web3.fromWei(cfToken.balanceOf(acc1).toString(10)) // = '261.4'
最後,若是咱們簽署一個調用不可用函數的事務,咱們將調用咱們的回退函數。 簽署一個像這樣的交易:
truffle(rsk)> web3.eth.sendTransaction({from: acc0, to: cfToken.address}) 0x4106a287fc60669bf9682a73ec4c457b094c086ec7408a5dea95d200688c4ee9
將返回一個日誌,其數據表示字符串Error 404:Function not found:P
(十六進制:'0x00 ... 00204572726f72203430343a2046756e6374696f6e206e6f7420666f756e64203a50'
)。
咱們的最後一個功能,即咱們不會由於顯而易見的緣由而執行,就是銷燬功能。咱們須要合約不被銷燬才能顯示交易。要調用,全部者應該這樣作:
truffle(rsk)> cfToken.destroy({from: acc0})
在演練的第二部分中,我展現了在RSK網絡中開發簡單智能合約的示例。 咱們已經看過:
正如咱們所看到的,RSK網絡用於Solidity Smart Contracts部署和交互的用法幾乎與以太坊節點中的相同。固然,這仍然是一個測試網絡,預計會出現問題和錯誤,主要是在節點中,但RSK Labs團隊在他們出現時儘量快地解決它們。隨着時間的推移,將實現穩健性。
======================================================================
分享一些以太坊、EOS、比特幣等區塊鏈相關的交互式在線編程實戰教程:
- java以太坊開發教程,主要是針對java和android程序員進行區塊鏈以太坊開發的web3j詳解。
- python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
- php以太坊,主要是介紹使用php進行智能合約開發交互,進行帳號建立、交易、轉帳、代幣開發以及過濾器和交易等內容。
- 以太坊入門教程,主要介紹智能合約與dapp應用開發,適合入門。
- 以太坊開發進階教程,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
- C#以太坊,主要講解如何使用C#開發基於.Net的以太坊應用,包括帳戶管理、狀態與交易、智能合約開發與交互、過濾器和交易等。
- EOS教程,本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、帳戶與錢包、發行代幣、智能合約開發與部署、使用代碼與智能合約交互等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。
- java比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Java代碼中集成比特幣支持功能,例如建立地址、管理錢包、構造裸交易等,是Java工程師不可多得的比特幣開發學習課程。
- php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Php代碼中集成比特幣支持功能,例如建立地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。
- tendermint區塊鏈開發詳解,本課程適合但願使用tendermint進行區塊鏈開發的工程師,課程內容即包括tendermint應用開發模型中的核心概念,例如ABCI接口、默克爾樹、多版本狀態庫等,也包括代幣發行等豐富的實操代碼,是go語言工程師快速入門區塊鏈開發的最佳選擇。
匯智網原創翻譯,轉載請標明出處。這裏是原文使用OpenZeppelin在RSK上進行ERC20代幣開發