千家信息网

以太坊中怎么用智能合约开发Hello World

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,这篇文章主要介绍"以太坊中怎么用智能合约开发Hello World"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"以太坊中怎么用智能合约开发Hello Worl
千家信息网最后更新 2025年02月02日以太坊中怎么用智能合约开发Hello World

这篇文章主要介绍"以太坊中怎么用智能合约开发Hello World"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"以太坊中怎么用智能合约开发Hello World"文章能帮助大家解决问题。

一、Solidity 语言

Solidity 是一种智能合约高级语言,运行在 Ethereum 虚拟机(EVM:Ethereum Virtual Machine)之上。
Solidity 的语法接近于 Javascript,是一种面向对象的语言,而且围绕着 Solidity 的各种开发工具链,都是使用属于 Javascript 生态系的 npm 来提供的。

二、编辑器

我目前是使用 Atom 搭配 solidity(linter-solium) 插件来开发。

三、Truffle 框架

Truffle 是针对基于以太坊的 Solidity 语言的一套开发框架,本身基于 Javascript。

四、工具安装

1、安装 Node.js 和 NPM;
2、安装 Truffle 框架,在终端运行命令:

$ sudo npm install -g truffle

安装 Truffle

3、安装 Truffle 客户端 EtherumJS TestRPC:

$ sudo npm install -g ganache-cli

安装 TestRPC

五、启动 TestRPC

使用以下命令来启动以太坊测试环境:

$ ganache-cli

启动以太坊测试环境

可以看到启动后自动建立了10个帐号(Accounts),与每个帐号对应的私钥(Private Key)。每个帐号中都有100个测试用的以太币(Ether)。要注意以太坊测试环境仅运行在內存中,因此每次重开时都会回到全新的状态。

六、创建项目

重新打开一个终端窗口,运行以下命令以创建项目:

$ mkdir SmartContractProject
$ cd SmartContractProject/
$ mkdir HelloWorld
$ cd HelloWorld/
$ truffle init

初始化 Truffle

HelloWorld 工程目录

QQ20180116-160844@2x.png

目录结构:

  • contracts/:Truffle默认的合约文件存放地址;

  • migrations/:存放发布的脚本文件;

  • test/:存放测试应用和合约的测试文件;

  • truffle.js 和 truffle-config.js:Truffle的配置文件。

七、新建 HelloWorld 合约

contracts 文件夹下新建 HelloWorld.sol 文件:

$ cd contracts/
$ truffle create contract HelloWorld

新建 HelloWorld 合约

QQ20180116-163158@2x.png

HelloWorld.sol 文件内容如下:

HelloWorld.sol

讲解:

pragma solidity ^0.4.4;

第一行指名目前使用的 solidity 版本,不同版本的 solidity 可能会编译出不同的 bytecode。^ 代表兼容 solidity 0.4.4 ~ 0.4.9 的版本。

 function HelloWorld() {   // constructor }}

contract 关键字类似于其他语言中较常见的 class。因为solidity 是专为智能合约(Contact)设计的语言,声明 contract 后即内置了开发智能合约所需的功能。也可以把这句理解为 class HelloWorld extends Contract

函数的结构与其他程序类似,但如果有传入的参数或回传值,需要指定参数或回传值的类型(type)。

八、向合约中添加新的方法

function sayHello() returns (string) {    return ("Hello World");}

添加新的方法

九、编译合约

现在执行 truffle compile 命令,我们可以将 HelloWorld.sol 原始码编译成 Ethereum bytecode

$ cd ..
$ truffle compile

编译合约

【注意出现了警告】
重新修改 HelloWorld.sol 文件中的方法:

pragma solidity ^0.4.4;contract HelloWorld {  function HelloWorld() public {    // constructor  }  function sayHello() public pure returns (string) {    return ("Hello World");}}

修改合约中的方法

保存后重新运行命令:

$ truffle compile

重新编译合约

命令运行成功后会多出一个 build 的目录,如下:

build 目录

HelloWorld 文件夹下面的 build/contracts 文件夹下面会看见 HelloWorld.json 文件:

HelloWorld.json

十、修改 truffle.js 文件内容:

添加以下内容到 truffle.js 文件并保存 :

networks: {        development: {            host:"localhost",            port:8545,            network_id:"*"  // 匹配任何network id        }    }

修改 truffle.js 文件

十一、部署合约

migrations 目录下创建移植文件:

$ cd migrations/
$ truffle create migration 2_deploy_helloworld

创建移植文件

migrations 目录

1516095208_2_deploy_helloworld.js 文件内容

修改文件名及文件内容如下:

var HelloWorld = artifacts.require("./HelloWorld.sol");module.exports = function(deployer) {  deployer.deploy(HelloWorld);};

修改移植文件内容

使用 artifacts.require 语句来取得准备部署的合约。
使用deployer.deploy 语句将合约部署到区块链上。
这边HelloWorldcontract 的名称而不是文件名。
因此可以用此语法读入任一 .sol 文件中的任一合约。

现在执行 truffle migrate 命令:

$ truffle migrate

部署合约

部署成功你会看到 启动 TestRPC 的终端窗口会有以下变化:

TestRPC 的终端窗口变化

十二、与合约互动

Truffle 提供命令行工具,执行 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 consoletruffle(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 中预载了 truffle-contract 函数库,以方便操作部署到区块链上的合约。
这边使用 HelloWorld.deployed().then 语句来取得 HelloWorld合约的 Instance(实例),并存到 contract 变量中,以方便后续的调用。

输入以下命令:

$ contract.sayHello.call()

与合约互动3

这里直接呼叫 contract.sayHello() 也会得到一样的结果。truffle-contract 提供使用 call() 来读取只读 (read only) 的数据,这样就不需提供 gas。因此如果遇到的操作需要向区块链写入数据,我们就不能用 call 语句了。

如此一来,我们已写好并部署完成了第一个智能合约,也验证了合约确实可以运作。

十三、加入新方法

我们在 HelloWorld.sol 中再加入一个 echo 方法,echo 方法接受输入一个参数,并回传传送的参数`:

function echo(string name) public pure returns (string) {    return name;}

加入新方法

由于更新了合约内容,我们需要先重新新编译一次,将编译结果部署到 testrpc 上,再透过 truffle console 执行看看结果。

$ truffle compile
$ truffle migrate --reset

移植重置

$ truffle console
$ let contract
HelloWorld.deployed().then(instance => contract = instance)

再次与合约互动1

再次与合约互动2

有一点需要注意的,是这次如果还是用 $ truffle migrate 命令,我们会得到如下信息:

$ truffle migrateUsing network 'development'.Network up to date.

Truffle 会告诉你现在网络上的合约都已是最新的,但事实上刚刚程序中新增的方法并没有更新到内存块链上。要更新内存块链上已部署的程序,需要改写 migrations 中的脚本,还好我们开发用的内存块链是怎么修改都没关系的 testrpc,可以使用 truffle migrate --reset 命令直接重新在 testrpc 上部署一次。

关于"以太坊中怎么用智能合约开发Hello World"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。

0