您好,登錄后才能下訂單哦!
這篇文章主要介紹“以太坊中怎么用智能合約開發(fā)Hello World”的相關(guān)知識,小編通過實(shí)際案例向大家展示操作過程,操作方法簡單快捷,實(shí)用性強(qiáng),希望這篇“以太坊中怎么用智能合約開發(fā)Hello World”文章能幫助大家解決問題。
Solidity 是一種智能合約高級語言,運(yùn)行在 Ethereum 虛擬機(jī)(EVM:Ethereum Virtual Machine)之上。
Solidity 的語法接近于 Javascript,是一種面向?qū)ο蟮恼Z言,而且圍繞著 Solidity 的各種開發(fā)工具鏈,都是使用屬于 Javascript 生態(tài)系的 npm 來提供的。
我目前是使用 Atom 搭配 solidity(linter-solium) 插件來開發(fā)。
Truffle 是針對基于以太坊的 Solidity 語言的一套開發(fā)框架,本身基于 Javascript。
1、安裝 Node.js 和 NPM;
2、安裝 Truffle 框架,在終端運(yùn)行命令:
$ sudo npm install -g truffle
安裝 Truffle
3、安裝 Truffle 客戶端 EtherumJS TestRPC:
$ sudo npm install -g ganache-cli
安裝 TestRPC
使用以下命令來啟動以太坊測試環(huán)境:
$ ganache-cli
啟動以太坊測試環(huán)境
可以看到啟動后自動建立了10個帳號(Accounts),與每個帳號對應(yīng)的私鑰(Private Key)。每個帳號中都有100個測試用的以太幣(Ether)。要注意以太坊測試環(huán)境僅運(yùn)行在內(nèi)存中,因此每次重開時都會回到全新的狀態(tài)。
重新打開一個終端窗口,運(yùn)行以下命令以創(chuàng)建項目:
$ mkdir SmartContractProject
$ cd SmartContractProject/
$ mkdir HelloWorld
$ cd HelloWorld/
$ truffle init
初始化 Truffle
HelloWorld 工程目錄
QQ20180116-160844@2x.png
目錄結(jié)構(gòu):
contracts/
:Truffle默認(rèn)的合約文件存放地址;
migrations/
:存放發(fā)布的腳本文件;
test/
:存放測試應(yīng)用和合約的測試文件;
truffle.js 和 truffle-config.js
:Truffle的配置文件。
在 contracts
文件夾下新建 HelloWorld.sol 文件:
$ cd contracts/
$ truffle create contract HelloWorld
新建 HelloWorld 合約
QQ20180116-163158@2x.png
HelloWorld.sol
文件內(nèi)容如下:
HelloWorld.sol
講解:
pragma solidity ^0.4.4;
第一行指名目前使用的 solidity 版本,不同版本的 solidity 可能會編譯出不同的 bytecode。^
代表兼容 solidity 0.4.4 ~ 0.4.9
的版本。
function HelloWorld() { // constructor } }
contract
關(guān)鍵字類似于其他語言中較常見的 class
。因為solidity 是專為智能合約(Contact)設(shè)計的語言,聲明 contract
后即內(nèi)置了開發(fā)智能合約所需的功能。也可以把這句理解為 class HelloWorld extends Contract
。
函數(shù)的結(jié)構(gòu)與其他程序類似,但如果有傳入的參數(shù)或回傳值,需要指定參數(shù)或回傳值的類型(type
)。
function sayHello() returns (string) { return ("Hello World"); }
添加新的方法
現(xiàn)在執(zhí)行 truffle compile
命令,我們可以將 HelloWorld.sol
原始碼編譯成 Ethereum bytecode
:
$ cd ..
$ truffle compile
編譯合約
【注意出現(xiàn)了警告】
重新修改 HelloWorld.sol
文件中的方法:
pragma solidity ^0.4.4; contract HelloWorld { function HelloWorld() public { // constructor } function sayHello() public pure returns (string) { return ("Hello World"); } }
修改合約中的方法
保存后重新運(yùn)行命令:
$ truffle compile
重新編譯合約
命令運(yùn)行成功后會多出一個 build
的目錄,如下:
build 目錄
在 HelloWorld
文件夾下面的 build/contracts
文件夾下面會看見 HelloWorld.json
文件:
HelloWorld.json
添加以下內(nèi)容到 truffle.js 文件并保存 :
networks: { development: { host:"localhost", port:8545, network_id:"*" // 匹配任何network id } }
修改 truffle.js 文件
在 migrations
目錄下創(chuàng)建移植文件:
$ cd migrations/
$ truffle create migration 2_deploy_helloworld
創(chuàng)建移植文件
migrations 目錄
1516095208_2_deploy_helloworld.js 文件內(nèi)容
修改文件名及文件內(nèi)容如下:
var HelloWorld = artifacts.require("./HelloWorld.sol"); module.exports = function(deployer) { deployer.deploy(HelloWorld); };
修改移植文件內(nèi)容
使用 artifacts.require
語句來取得準(zhǔn)備部署的合約。
使用deployer.deploy
語句將合約部署到區(qū)塊鏈上。
這邊HelloWorld
是 contract
的名稱而不是文件名。
因此可以用此語法讀入任一 .sol
文件中的任一合約。
現(xiàn)在執(zhí)行 truffle migrate
命令:
$ truffle migrate
部署合約
部署成功你會看到 啟動 TestRPC 的終端窗口會有以下變化:
TestRPC 的終端窗口變化
Truffle 提供命令行工具,執(zhí)行 truffle console
命令后,可用Javascript 來和剛剛部署的合約互動:
$ cd ..
$ truffle console
$ HelloWorld.deployed().then(instance => contract = instance)
與合約互動1
與合約互動2
yutaos-MacBook-Pro:migrations yutaozhang$ cd .. yutaos-MacBook-Pro:HelloWorld yutaozhang$ truffle console truffle(development)> HelloWorld.deployed().then(instance => contract = instance) TruffleContract { constructor: { [Function: TruffleContract] _static_methods: { setProvider: [Function: setProvider], new: [Function: new], at: [Function: at], deployed: [Function: deployed], defaults: [Function: defaults], hasNetwork: [Function: hasNetwork], isDeployed: [Function: isDeployed], detectNetwork: [Function: detectNetwork], setNetwork: [Function: setNetwork], resetAddress: [Function: resetAddress], link: [Function: link], clone: [Function: clone], addProp: [Function: addProp], toJSON: [Function: toJSON] }, _properties: { contract_name: [Object], contractName: [Object], abi: [Object], network: [Function: network], networks: [Function: networks], address: [Object], links: [Function: links], events: [Function: events], binary: [Function: binary], deployedBinary: [Function: deployedBinary], unlinked_binary: [Object], bytecode: [Object], deployedBytecode: [Object], sourceMap: [Object], deployedSourceMap: [Object], source: [Object], sourcePath: [Object], ast: [Object], compiler: [Object], schema_version: [Function: schema_version], schemaVersion: [Function: schemaVersion], updated_at: [Function: updated_at], updatedAt: [Function: updatedAt] }, _property_values: {}, _json: { contractName: 'HelloWorld', abi: [Array], bytecode: '0x6060604052341561000f57600080fd5b6101578061001e6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef5fb05b14610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc610117565b6040805190810160405280600b81526020017f48656c6c6f20576f726c64000000000000000000000000000000000000000000815250905090565b6020604051908101604052806000815250905600a165627a7a72305820b825548240e74063f6a0c0dd2a2b787ed288e3359cb7682b670288211d37f14f0029', deployedBytecode: '0x606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef5fb05b14610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc610117565b6040805190810160405280600b81526020017f48656c6c6f20576f726c64000000000000000000000000000000000000000000815250905090565b6020604051908101604052806000815250905600a165627a7a72305820b825548240e74063f6a0c0dd2a2b787ed288e3359cb7682b670288211d37f14f0029', sourceMap: '25:164:0:-;;;49:53;;;;;;;;25:164;;;;;;', deployedSourceMap: '25:164:0:-;;;;;;;;;;;;;;;;;;;;;;;;106:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:2;8:100;;;99:1;94:3;90;84:5;80:1;75:3;71;64:6;52:2;49:1;45:3;40:15;;8:100;;;12:14;3:109;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106:80:0;147:6;;:::i;:::-;161:22;;;;;;;;;;;;;;;;;;;;106:80;:::o;25:164::-;;;;;;;;;;;;;;;:::o', source: 'pragma solidity ^0.4.4;\n\ncontract HelloWorld {\n function HelloWorld() public {\n // constructor\n }\n\n function sayHello() public pure returns (string) {\n return ("Hello World");\n}\n\n}\n', sourcePath: '/Users/yutaozhang/SmartContractProject/HelloWorld/contracts/HelloWorld.sol', ast: [Object], compiler: [Object], networks: [Object], schemaVersion: '1.0.1', updatedAt: '2018-01-16T09:55:58.496Z' }, setProvider: [Function: bound setProvider], new: [Function: bound new], at: [Function: bound at], deployed: [Function: bound deployed], defaults: [Function: bound defaults], hasNetwork: [Function: bound hasNetwork], isDeployed: [Function: bound isDeployed], detectNetwork: [Function: bound detectNetwork], setNetwork: [Function: bound setNetwork], resetAddress: [Function: bound resetAddress], link: [Function: bound link], clone: [Function: bound clone], addProp: [Function: bound addProp], toJSON: [Function: bound toJSON], web3: Web3 { _requestManager: [Object], currentProvider: [Object], eth: [Object], db: [Object], shh: [Object], net: [Object], personal: [Object], bzz: [Object], settings: [Object], version: [Object], providers: [Object], _extend: [Object] }, class_defaults: { from: '0xcb009af857f4e65d3b234f491ffebe76cee6cbe7', gas: 6721975, gasPrice: 100000000000 }, currentProvider: HttpProvider { host: 'http://localhost:8545', timeout: 0, user: undefined, password: undefined, send: [Function], sendAsync: [Function], _alreadyWrapped: true }, network_id: '1516087157119' }, abi: [ { constant: true, inputs: [], name: 'sayHello', outputs: [Array], payable: false, stateMutability: 'pure', type: 'function' }, { inputs: [], payable: false, stateMutability: 'nonpayable', type: 'constructor' } ], contract: Contract { _eth: Eth { _requestManager: [Object], getBalance: [Object], getStorageAt: [Object], getCode: [Object], getBlock: [Object], getUncle: [Object], getCompilers: [Object], getBlockTransactionCount: [Object], getBlockUncleCount: [Object], getTransaction: [Object], getTransactionFromBlock: [Object], getTransactionReceipt: [Object], getTransactionCount: [Object], call: [Object], estimateGas: [Object], sendRawTransaction: [Object], signTransaction: [Object], sendTransaction: [Object], sign: [Object], compile: [Object], submitWork: [Object], getWork: [Object], coinbase: [Getter], getCoinbase: [Object], mining: [Getter], getMining: [Object], hashrate: [Getter], getHashrate: [Object], syncing: [Getter], getSyncing: [Object], gasPrice: [Getter], getGasPrice: [Object], accounts: [Getter], getAccounts: [Object], blockNumber: [Getter], getBlockNumber: [Object], protocolVersion: [Getter], getProtocolVersion: [Object], iban: [Object], sendIBANTransaction: [Function: bound transfer] }, transactionHash: null, address: '0x742c7a36d3a2b65a5607180fdee7fd5befc8a164', abi: [ [Object], [Object] ], sayHello: { [Function: bound ] request: [Function: bound ], call: [Function: bound ], sendTransaction: [Function: bound ], estimateGas: [Function: bound ], getData: [Function: bound ], '': [Circular] }, allEvents: [Function: bound ] }, sayHello: { [Function] call: [Function], sendTransaction: [Function], request: [Function: bound ], estimateGas: [Function] }, sendTransaction: [Function], send: [Function], allEvents: [Function: bound ], address: '0x742c7a36d3a2b65a5607180fdee7fd5befc8a164', transactionHash: null } truffle(development)>
講解:
HelloWorld.deployed().then(instance => contract = instance)
truffle console
中預(yù)載了 truffle-contract
函數(shù)庫,以方便操作部署到區(qū)塊鏈上的合約。
這邊使用 HelloWorld.deployed().then
語句來取得 HelloWorld
合約的 Instance
(實(shí)例),并存到 contract
變量中,以方便后續(xù)的調(diào)用。
輸入以下命令:
$ contract.sayHello.call()
與合約互動3
這里直接呼叫 contract.sayHello()
也會得到一樣的結(jié)果。truffle-contract
提供使用 call()
來讀取只讀 (read only)
的數(shù)據(jù),這樣就不需提供 gas
。因此如果遇到的操作需要向區(qū)塊鏈寫入數(shù)據(jù),我們就不能用 call
語句了。
如此一來,我們已寫好并部署完成了第一個智能合約,也驗證了合約確實(shí)可以運(yùn)作。
我們在 HelloWorld.sol
中再加入一個 echo
方法,echo
方法接受輸入一個參數(shù),并回傳傳送的參數(shù)`:
function echo(string name) public pure returns (string) { return name; }
加入新方法
由于更新了合約內(nèi)容,我們需要先重新新編譯一次,將編譯結(jié)果部署到 testrpc
上,再透過 truffle console
執(zhí)行看看結(jié)果。
$ truffle compile
$ truffle migrate --reset
移植重置
$ truffle console
$ let contract
HelloWorld.deployed().then(instance => contract = instance)
再次與合約互動1
再次與合約互動2
有一點(diǎn)需要注意的,是這次如果還是用 $ truffle migrate
命令,我們會得到如下信息:
$ truffle migrate Using network 'development'. Network up to date.
Truffle 會告訴你現(xiàn)在網(wǎng)絡(luò)上的合約都已是最新的,但事實(shí)上剛剛程序中新增的方法并沒有更新到內(nèi)存塊鏈上。要更新內(nèi)存塊鏈上已部署的程序,需要改寫 migrations
中的腳本,還好我們開發(fā)用的內(nèi)存塊鏈?zhǔn)窃趺葱薷亩紱]關(guān)系的 testrpc
,可以使用 truffle migrate --reset
命令直接重新在 testrpc
上部署一次。
關(guān)于“以太坊中怎么用智能合約開發(fā)Hello World”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點(diǎn)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。