智能合约开发环境搭建及Hello World合约
945坏男人
发表于 2022-11-7 00:10:06
123
0
0
就先学习任何编程语言一样,入门的第一个程序都是HelloWorld。今天我们来一步一步从搭建以太坊智能合约开发环境开始,讲解智能合约的HelloWorld如何编写。1 j, w7 N+ m* X; m- ?1 ]
9 A3 |: A5 {' s' S# h! A+ `
开发环境搭建3 |* m6 { @$ q( x7 L: F2 K
Solidity安装5 G& k& K2 Y" }8 }" ^
强烈建议新手使用Remix-SolidityIDE来进行开发。
Remix是一个基于浏览器的Solidity,就可以不用安装Solidity,本文的HelloWorld教程也将基于RemixSolidityIDE来进行。3 L, X8 v z9 E/ P1 u# e
d3 m( [2 n8 {7 w5 F
如果你想自己安装请参考Solidity安装指引。
更新,开发环境搭建还可以看另一篇文章:搭建智能合约开发环境RemixIDE及使用。4 b1 h$ e, G4 e' R. q- B( |' O
geth安装: c/ C- n' F4 u: S( K6 G
0 `& E% g4 `9 k: H" j% C
Mac下安装命令如下:其他平台参考:geth官方安装指引
0 V. i6 N- J c/ y# w' W
brewtapethereum/ethereum
brewinstallethereum
; o$ X) z& x8 p3 {5 T! b" V
brew是Mac下的包管理工具,和Ubuntu里的apt-get类似
安装完以后,就是把geth控制台启动。4 W* G0 d# l% m1 g3 g" ]+ F) m
启动环境/ C3 O2 c7 c+ Y% N# P n0 s
) r1 C) B5 X& V
在入门篇讲过,geth是一个以太坊客户端,现在利用geth启动一个以太坊(开发者)网络节点。
geth--datadirtestNet--devconsole2>>test.log! |& ~0 H7 ?$ `
8 ^+ b9 _5 b( V S, |, F9 J& R
执行命名后,会进入geth控制台,这时光标停在一个向右的箭头处,像这样
命令参数说明3 C2 J& _8 ~8 N( x3 T) a
–dev启用开发者网络(模式),开发者网络会使用POA共识,默认预分配一个开发者账户并且会自动开启挖矿。" F, v, _3 a4 V* \5 p8 g$ B
–datadir后面的参数是区块数据及秘钥存放目录。7 A3 |* ~3 i- W
第一次输入命令后,它会放在当前目录下新建一个testNet目录来存放数据。
console进入控制台
+ O/ I& i8 D+ w3 g* c% |; N( c
2>>test.log表示把控制台日志输出到test.log文件
为了更好的理解,建议新开一个命令行终端,实时显示日志:$ z( O0 L+ a8 D, F0 E) i
tail-ftest.log" u) U- j/ b* n; B( u# C9 a( F
- p8 s Y8 {7 L8 ~ s, X
准备账户
部署智能合约需要一个外部账户,我们先来看看分配的开发者账户,在控制台使用以下命令查看账户:
>eth.accounts$ T9 ]+ M. h% @( D6 R
, J' ]% G" L9 N- d) k$ G6 [
回车后,返回一个账户数组,里面有一个默认账户,如:4 s& \* s& j% e1 F P
也可以使用personal.listAccounts查看账户,+ _0 e) j- i8 n! x3 e, W- V
再来看一下账户里的余额,使用一下命令:. h# w1 g u- T3 y1 M
>eth.getBalance(eth.accounts[0])2 m, V/ d4 r3 s0 j$ W
3 {( p' O- d \& [
**eth.accounts[0]**表示账户列表第一个账户
7 V0 \. T# o4 I1 u4 P: ]
回车后,可以看到大量的余额,如:7 u. f+ a; e+ H' \: M
1.15792089237316195423570985008687907853269…e+77# b6 J. K+ |6 ^! V J& n2 F+ Z
开发者账户因余额太多,如果用这个账户来部署合约时会无法看到余额变化,为了更好的体验完整的过程,这里选择创建一个新的账户。
) X- X; m7 Y1 H3 [6 y. U% {! u1 _5 ~* M
创建账户+ g! p. J9 f: P6 C8 p+ E9 s
# m6 w: {' C8 R
使用以下命令创建账户:
>personal.newAccount("TinyXiong")- d. t2 d5 ^# O, L, H# d3 O3 `
' q; p6 V! D3 b! m9 L
TinyXiong为新账户的密码,回车后,返回一个新账户。
) e4 b ~6 N2 Y
这时我们查看账户列表:
>eth.accounts% P9 Z. c5 i6 h
9 ?& `9 \3 ^6 r7 K8 d
可以看到账户数组你包含两个账户,新账户在第二个(索引为1)位置。
+ l5 l+ [2 A, o
现在看看账户的余额:
8 y3 k6 E7 |5 {$ |5 z4 L1 g& |
>eth.getBalance(eth.accounts[1])+ P4 |! {' N- T
0
) M" [ F" s0 V3 U9 t
回车后,返回的是0,新账户是0。结果如:
! p) l4 N$ k0 n9 U( `1 v
给新账户转账7 W2 B, i3 \2 q( _
我们知道没有余额的账户是没法部署合约的,那我们就从默认账户转1以太币给新账户,使用以下命令(请使用你自己eth.accounts对应输出的账户):( L' }! L. C8 Q# O' n* x- B
+ j( m: F3 {) c; E% _* r' |
eth.sendTransaction({from:'0xb0ebe17ef0e96b5c525709c0a1ede347c66bd391',to:'0xf280facfd60d61f6fd3f88c9dee4fb90d0e11dfc',value:web3.toWei(1,"ether")})! f" z/ K/ n$ E
在打开的tail-ftest.log日志终端里,可以同时看到挖矿记录
6 W6 U" i( h4 x
再次查看新账户余额,可以新账户有1个以太币
/ v# \/ g3 _2 h% }9 c, |
解锁账户
在部署合约前需要先解锁账户(就像银行转账要输入密码一样),使用以下命令:9 e7 i9 |- ]: L
) ]4 i( h' C1 X
personal.unlockAccount(eth.accounts[1],"TinyXiong");/ b# M3 y. Z" i! f4 F( A; U ]' \
8 [+ O) `' t% d' @" C/ _
“TinyXiong”是之前创建账户时的密码8 N4 q; p% v, S, L4 h
解锁成功后,账户就准备完毕啦,接下来就是编写合约代码。
编写合约代码
# W/ Y2 I' s) R; Y
现在我们来开始编写第一个智能合约代码,solidity代码如下:6 U* L' f" l! H% Y% W8 o, i
pragmasolidity^0.4.18;
; _8 `' `# P9 g! U7 t, K4 O
contracthello{ S2 i3 Y2 o4 O
stringgreeting;
9 X* {) D/ c- T
functionhello(string_greeting)public{
greeting=_greeting;5 @+ c' e c* S4 D( H
}! F% Q4 `! [! [2 j+ O" F
functionsay()constantpublicreturns(string){
1 u- T4 u; v0 u9 K, o
returngreeting;; i4 E! G* X) \) s$ {% U& y; Y+ D
}/ t a" l9 X% x; s5 S
}
) r a: J( {* T7 D
简单解释下,我们定义了一个名为hello的合约,在合约初始化时保存了一个字符串(我们会传入helloworld),每次调用say返回字符串。! q4 Y5 W, {1 K6 h4 E9 h
把这段代码写(拷贝)到Browser-Solidity,如果没有错误,点击Details获取部署代码,) H/ F& ]! q/ i/ Z- h( i
' Y+ {5 z- v4 M" L1 c
如' R2 e& H% S* p
0 x5 t2 X6 T6 k% Y
在弹出的对话框中找到WEB3DEPLOY部分,点拷贝,粘贴到编辑器后,修改初始化字符串为helloworld。
+ v0 |& Y0 z9 v6 M
solidity在博文写作时(2017/11/24),版本为0.4.18,solidity发展非常快,solidity版本之间有可能不能兼容,这是你可以在Browser-Solidity的Settings里选择对应的编译器版本。$ }' b6 h4 Y* P4 f K* f2 b( S
Browser-Solidity也不停的更新中,截图可能和你看到的界面不一样。
X: A- ?+ j$ D2 E4 i8 j
部署合约
$ U$ i, W! w) C4 k" |
Browser-Solidity生成的代码,拷贝到编辑器里修改后的代码如下0 f( }7 e" B @1 F3 C' I8 P9 g
var_greeting="HelloWorld";
varhelloContract=web3.eth.contract([{"constant":true,"inputs":[],"name":"say","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_greeting","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]);
0 S/ U5 P# w! L
varhello=helloContract.new(
, \+ L9 s \- [$ W
_greeting,
5 p$ g8 Y' s% m& K
{0 z$ E- i6 O) a- Y; E
from:web3.eth.accounts[1],' b( g! a. Y! `% R
data:'0x6060604052341561000f57600080fd5b6040516102b83803806102b8833981016040528080518201919050508060009080519060200190610041929190610048565b50506100ed565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061008957805160ff19168380011785556100b7565b828001600101855582156100b7579182015b828111156100b657825182559160200191906001019061009b565b5b5090506100c491906100c8565b5090565b6100ea91905b808211156100e65760008160009055506001016100ce565b5090565b90565b6101bc806100fc6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063954ab4b214610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc61017c565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101725780601f1061014757610100808354040283529160200191610172565b820191906000526020600020905b81548152906001019060200180831161015557829003601f168201915b5050505050905090565b6020604051908101604052806000815250905600a165627a7a723058204a5577bb3ad30e02f7a3bdd90eedcc682700d67fc8ed6604d38bb739c0655df90029',
gas:'4700000'4 x5 e' c9 P6 u9 ]/ z
},function(e,contract){" w& w' S3 J. y1 u, b, e
console.log(e,contract);2 r1 z, }- Z7 f
% p" q- G2 r e7 t# [8 W, b X1 \
if(typeofcontract.address!=='undefined'){
console.log('Contractmined!address:'+contract.address+'transactionHash:'+contract.transactionHash);
9 j% q9 N* [2 l9 H1 ] [
}. a) F/ x- y/ w& `" ^9 t: b; L
});
" Q/ ?0 y* l$ k% G1 Y; n; H
第1行:修改字符串为HelloWorld
第2行:修改合约变量名4 P6 _" T1 k$ } [( v
8 z! {( o2 } J! M0 P# D% ]
第3行:修改合约实例变量名,之后可以直接用实例调用函数。8 M; R# \# k4 Z; q2 b$ a A' z7 g
第6行:修改部署账户为新账户索引,即使用新账户来部署合约。
: l! `$ p- k8 a3 K$ F
第8行:准备付的gas费用,IDE已经帮我们预估好了。
" h5 Q1 M3 v6 a5 s% ^
第9行:设置部署回调函数。
! e5 N1 r* s% _1 [7 f' a; ?
拷贝回geth控制台里,回车后,看到输出如:5 Y1 \' s# n, V; c3 `! ?6 H
0 g5 I6 P: F8 _; d' s5 G
Contractmined!address:0x79544078dcd9d560ec3f6eff0af42a9fc84c7d19transactionHash:0xe2caab22102e93434888a0b8013a7ae7e804b132e4a8bfd2318356f6cf0480b35 |$ O, G X* k) M7 v+ D1 ?' t: f
: N' w: g9 ~6 C! y: \
说明合约已经部署成功。
8 V# n! Y. f5 z7 p+ [
在打开的tail-ftest.log日志终端里,可以同时看到挖矿记录
/ ~7 t1 L( E9 z) u' ?; `* y" ]# K
现在我们查看下新账户的余额:
( h9 L( C O W% t e( Z
>eth.getBalance(eth.accounts[1])
8 q! d2 @, ?) M
是不是比之前转账的余额少呀!
运行合约$ r6 I: ]7 n# p5 c' K- m$ l
3 @: H5 p6 E \# v
>hello.say()
2 w4 W' Q( q) o9 \
"HelloWorld"
' b$ a4 J* R) K* h! J
输出HelloWorld,我们第一个合约HelloWorld,成功运行了。
运行截图如下:0 R: ]2 e- V. d6 A" F" ], {0 P
' X) W2 u# J- k' c& ~6 U; Y
第一个合约的意义更重要的是体验智能合约开发流程,对于初学者一些可以选择先放弃一些细节,开发流程打通之后,可以增强信心进行下一步的学习。
作者:@xilibi2003
成为第一个吐槽的人