第三课 如何实现以太坊最简智能合约“Hello World”的运行

【本文目标】

完成以太坊最简智能合约“Hello World”的编写和运行

【技术收获】

跟随本文实践,你将可以有以下收获:

  1. 启动GETH以太坊钱包环境
  2. 准备账户
  3. 创建账户
  4. 给新账户转账
  5. 解锁账户
  6. 编写合约代码
  7. 部署合约
  8. 运行合约

【实操课程列表】

第一课 如何在WINDOWS环境下搭建以太坊开发环境

第二课 如何实现以太坊最简智能合约“Hello World”的运行

第四课 以太坊开发框架Truffle从入门到实战

第六课 技术小白如何开发一个DAPP区块链应用(以宠物商店为例)

第七课 技术小白如何在45分钟内发行通证(TOKEN)并上线交易

第八课 如何调试以太坊官网的智能合约众筹案例

【说明】未列出的课程为知识普及的非实操类课程,所有区块链文章参考“区块链入口”专栏。

1. 启动GETH以太坊钱包环境

如果你对于以太坊智能合约开发还没有概念(本文会假设你已经知道这些概念),建议先阅读入门篇。 就先学习任何编程语言一样,入门的第一个程序都是Hello World。今天我们来一步一步从搭建以太坊智能合约开发环境开始,讲解智能合约的Hello World如何编写。

【说明】强烈建议新手使用Browser-Solidity来进行开发。

Browser-Solidity是一个基于浏览器的Solidity,就可以不用安装Solidity,本文的Hello World教程也将基于Browser-Solidity来进行。如果你想自己安装请参考Solidity安装指引。

geth是一个以太坊客户端,现在利用geth启动一个以太坊(开发者)网络节点。

geth --datadir testNet --dev console 2>> test.log

执行命名后,会进入geth控制台,这时光标停在一个向右的箭头处,像这样:

命令参数说明:

–dev 启用开发者网络(模式),开发者网络会使用POA共识,默认预分配一个开发者账户并且会自动开启挖矿。

–datadir 后面的参数是区块数据及秘钥存放目录。

第一次输入命令后,它会放在当前目录下新建一个testNet目录来存放数据。

console 进入控制台

2>> test.log 表示把控制台日志输出到test.log文件为了更好的理解,建议新开一个命令行终端,实时显示日志:

tail -f test.log

输出截图:

Xshell建立一个新的窗口用于输出LOG结果

2. 准备账户

部署智能合约需要一个外部账户,我们先来看看分配的开发者账户,在控制台使用以下命令查看账户:

eth.accounts

回车后,返回一个账户数组,里面有一个默认账户,

也可以使用personal.listAccounts查看账户。

personal.listAccounts

本文作者已创建了一个账号,共有2个账号了:

eth.getBalance(eth.accounts[0])表示账户列表第一个账户

回车后,可以看到大量的余额,如:

1.15792089237316195423570985008687907853269… e+77

开发者账户因余额太多,如果用这个账户来部署合约时会无法看到余额变化,为了更好的体验完整的过程,这里选择创建一个新的账户。

3. 创建账户

使用以下命令创建账户:

personal.newAccount("duncanwang")

duncanwang为新账户的密码,回车后,返回一个新账户。

可以看到账户数组包含了3个账户,新账户在第三个(索引为2)位置。

现在看看账户的新余额,可以发现是0.

eth.accounts

eth.getBalance(eth.accounts[2])

截图如下:

4. 给新账户转账

我们知道没有余额的账户是没法部署合约的,那我们就从默认账户转1以太币给新账户,使用以下命令(请使用你自己eth.accounts对应输出的账户):

eth.sendTransaction({from: '0x8cfa24a398efd88de3843d7834cb07fce41e6f46', to: '0x0f1b9da153d910f6ae150145924615c23bbf5176', value: web3.toWei(99, "ether")})

eth.getBalance(eth.accounts[2])

在打开的tail -f test.log日志终端里,可以同时看到挖矿记录

再次查看新账户余额,可以新账户有99个以太币(显示的单位是wei,所以有18个0) 。

5. 解锁账户

在部署合约前需要先解锁账户(就像银行转账要输入密码一样),使用以下命令:

personal.unlockAccount(eth.accounts[2],"duncanwang");

“duncanwang” 是之前创建账户时的密码

解锁成功后,账户就准备完毕啦,接下来就是编写合约代码。

【说明】

geth的这些函数的接口文档是哪个呢?需要学习GETH所有的库函数,可参考官网文档

1,admin,debug,miner,personal,txpool实例的接口函数[Console的描述]

https://github.com/ethereum/go-ethereum/wiki/Management-APIs

2,eth实例的接口函数[例如eth_protocolVersion去除下划线为eth.protocolVersion]

https://github.com/ethereum/wiki/wiki/JSON-RPC

6. 编写合约代码

现在我们来开始编写第一个智能合约代码,solidity代码如下:

pragma solidity ^0.4.21; contract hello { string greeting; function hello(string _greeting) public { greeting = _greeting; } function say() constant public returns (string) { return greeting; } }

简单解释下,我们定义了一个名为hello的合约,在合约初始化时保存了一个字符串(我们会传入hello world),每次调用say返回字符串。

把这段代码写(拷贝)到Browser-Solidity,如果没有错误,点击Details获取部署代码,如:

在弹出的对话框中找到WEB3DEPLOY部分,点拷贝,粘贴到编辑器后,修改初始化字符串为hello world。

solidity在博文写作时(2018/3/30),版本为0.4.21,solidity发展非常快,solidity版本之间有可能不能兼容,这是你可以在Browser-Solidity的Settings里选择对应的编译器版本。 Browser-Solidity也不停的更新中,截图可能和你看到的界面不一样。7. 部署合约

Browser-Solidity生成的代码,拷贝到编辑器里修改后的代码如下:

var _greeting5 ="hello world" ; var helloContract5 = web3.eth.contract([{"constant":true,"inputs":[],"name":"say","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_greeting5","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]); var hello = helloContract5.new( _greeting5, { from: web3.eth.accounts[2], data: '0x6060604052341561000f57600080fd5b6040516102b83803806102b8833981016040528080518201919050508060009080519060200190610041929190610048565b50506100ed565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061008957805160ff19168380011785556100b7565b828001600101855582156100b7579182015b828111156100b657825182559160200191906001019061009b565b5b5090506100c491906100c8565b5090565b6100ea91905b808211156100e65760008160009055506001016100ce565b5090565b90565b6101bc806100fc6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063954ab4b214610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc61017c565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101725780601f1061014757610100808354040283529160200191610172565b820191906000526020600020905b81548152906001019060200180831161015557829003601f168201915b5050505050905090565b6020604051908101604052806000815250905600a165627a7a72305820427519fec7c58323ba692e485469b971a098bccaeb0ddf7a48f15b917d2d13910029', gas: '4700000' }, function (e, contract){ console.log(e, contract); if (typeof contract.address !== 'undefined') { console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); } })

【注意】

第1行:修改变量名为_geeting5, 修改字符串为Hello World

第2行:合约变量名为helloContract5,里面引用改为_greeting5

第3行:修改合约实例变量名为helloContract5,之后可以直接用实例调用函数。

第6行:修改部署账户为新账户索引,此处改为[2],即使用新账户来部署合约。

第8行:准备付的gas费用,IDE已经帮我们预估好了。

第9行:设置部署回调函数。

其中变量名为全局的,_geeting5仅为举例表示新定义的变量。

拷贝会geth控制台里,回车后,看到输出,说明合约已经部署成功。

在打开的tail -f test.log日志终端里,可以同时看到挖矿记录

现在我们查看下新账户的余额:

eth.getBalance(eth.accounts[2])

输出结果不再是99个以太币,比以前少了。

8. 运行合约

执行一下合约函数:

hello.say()

输出Hello World,我们第一个合约Hello World,成功运行了。

一个合约的意义更重要的是体验智能合约开发流程,对于初学者一些可以选择先放弃一些细节,开发流程打通之后,可以增强信心进行下一步的学习。


参考文档

1,智能合约开发环境搭建及Hello World合约

2,GETH账户管理接口文档

3,GETH JSON-RPC 接口调用函数

4, GETH API接口管理

知识对接服务:

辉哥和欧阳哥哥在知识星球开通了区块链入门专栏,用于存放简书区块链入门专栏文章的工程源码等内容,并建立专项微信群用于技术交流,欢迎加入。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

微信号已复制,请打开微信添加咨询详情!
-->