溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

以太坊中怎么用智能合約開發(fā)Hello World

發(fā)布時間:2022-01-15 15:00:11 來源:億速云 閱讀:124 作者:iii 欄目:互聯(lián)網(wǎng)科技

這篇文章主要介紹“以太坊中怎么用智能合約開發(fā)Hello World”的相關(guān)知識,小編通過實(shí)際案例向大家展示操作過程,操作方法簡單快捷,實(shí)用性強(qiáng),希望這篇“以太坊中怎么用智能合約開發(fā)Hello World”文章能幫助大家解決問題。

一、Solidity 語言

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 框架

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

五、啟動 TestRPC

使用以下命令來啟動以太坊測試環(huán)境:

$ ganache-cli

啟動以太坊測試環(huán)境

可以看到啟動后自動建立了10個帳號(Accounts),與每個帳號對應(yīng)的私鑰(Private Key)。每個帳號中都有100個測試用的以太幣(Ether)。要注意以太坊測試環(huán)境僅運(yùn)行在內(nèi)存中,因此每次重開時都會回到全新的狀態(tài)。

六、創(chuàng)建項目

重新打開一個終端窗口,運(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的配置文件。

七、新建 HelloWorld 合約

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

十、修改 truffle.js 文件內(nèi)容:

添加以下內(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ū)塊鏈上。
這邊HelloWorldcontract 的名稱而不是文件名。
因此可以用此語法讀入任一 .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)。

向AI問一下細(xì)節(jié)

免責(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)容。

AI