智能合约开发环境搭建及Hello World合约
945坏男人
发表于 2022-11-7 00:10:06
126
0
0
就先学习任何编程语言一样,入门的第一个程序都是HelloWorld。今天我们来一步一步从搭建以太坊智能合约开发环境开始,讲解智能合约的HelloWorld如何编写。2 w) l+ k" V9 r# ?
* u) K; a# L- o8 i1 q3 ?
开发环境搭建8 @# K/ O0 \/ y1 ]5 A4 K7 J# f
Solidity安装7 S) ?; J( _/ V0 ~* X( z
, e/ A" e9 }5 c0 R" l, k
强烈建议新手使用Remix-SolidityIDE来进行开发。6 T4 J; G6 G s
) _( h" `* a# l" d2 @
Remix是一个基于浏览器的Solidity,就可以不用安装Solidity,本文的HelloWorld教程也将基于RemixSolidityIDE来进行。$ J& B* d/ o6 r+ M" ~$ S
6 C+ t3 u" q% [, W6 W2 P$ v
如果你想自己安装请参考Solidity安装指引。9 F. q6 K0 W2 B( x2 u$ o, S+ b
更新,开发环境搭建还可以看另一篇文章:搭建智能合约开发环境RemixIDE及使用。
- @; ^& D3 B0 C' ]
geth安装. O& h! a+ U( T) y6 P1 i, j
Mac下安装命令如下:其他平台参考:geth官方安装指引; Q5 y, m: W: A
$ {& X+ a+ n0 d/ p h$ z% X' H$ O
brewtapethereum/ethereum
brewinstallethereum
9 v, S0 @$ }; |& G$ U, ], s
brew是Mac下的包管理工具,和Ubuntu里的apt-get类似; D( G4 \2 ?# O- A7 }. q9 ^
安装完以后,就是把geth控制台启动。
% ^: o8 ^# L& `6 F/ z
启动环境, R9 _) D( L: C5 Z
在入门篇讲过,geth是一个以太坊客户端,现在利用geth启动一个以太坊(开发者)网络节点。- h( \* ?5 r) G3 O- X: u; ^6 Y2 Y
' {: n$ M& k0 Q( M/ P) \
geth--datadirtestNet--devconsole2>>test.log- V8 H2 B3 `1 V* j' {& t
执行命名后,会进入geth控制台,这时光标停在一个向右的箭头处,像这样6 \( r5 e+ p; h
命令参数说明
9 q* e8 \- ~: `# H2 R
–dev启用开发者网络(模式),开发者网络会使用POA共识,默认预分配一个开发者账户并且会自动开启挖矿。
; o+ w* a0 B: N
–datadir后面的参数是区块数据及秘钥存放目录。* p- a. I5 ~( L; ~; }! G! i
! L# B0 W/ }) S% K) N8 z$ |$ V: W
第一次输入命令后,它会放在当前目录下新建一个testNet目录来存放数据。* j. S7 r4 }, N' @
console进入控制台6 Q5 f) F' B2 i% h8 k- O7 @8 n
+ j9 i% Q+ S" g9 q$ d7 Y3 [* H5 O
2>>test.log表示把控制台日志输出到test.log文件
. g# b# j3 ?8 C: V
为了更好的理解,建议新开一个命令行终端,实时显示日志:
9 A2 M- X; l! z8 O. X
tail-ftest.log
# V7 @9 B1 J& b3 l- G
准备账户) h e3 m& g+ L) {+ j I' r. P7 J
! T7 W, n5 A* j* v
部署智能合约需要一个外部账户,我们先来看看分配的开发者账户,在控制台使用以下命令查看账户:
>eth.accounts
回车后,返回一个账户数组,里面有一个默认账户,如:3 ~+ T- Z- }4 z# Q) `, _2 E6 Z( n
也可以使用personal.listAccounts查看账户,
1 r2 C7 [* s- C% h q
再来看一下账户里的余额,使用一下命令:
>eth.getBalance(eth.accounts[0])- i+ Q4 b; K( i- E' B2 c0 \
# t% @& l3 N7 ?+ l _
**eth.accounts[0]**表示账户列表第一个账户1 {: q o4 g2 i4 f3 z( Z' _5 ~, S3 o
回车后,可以看到大量的余额,如:
8 l0 g5 `2 {, w* Z
1.15792089237316195423570985008687907853269…e+77: U! u0 M; M" \5 m4 i W
开发者账户因余额太多,如果用这个账户来部署合约时会无法看到余额变化,为了更好的体验完整的过程,这里选择创建一个新的账户。
6 `* U ]1 W* ], w3 @1 n2 _
创建账户
9 M B1 U, X1 D( i [5 K( h- W/ h; I
使用以下命令创建账户:; s9 y$ p9 _% |9 o6 \
, d$ P3 J1 Y& i$ K5 R0 p) [2 ^% I
>personal.newAccount("TinyXiong")$ I! ]! _* J- v2 ^- w% p
Z$ t, b" { v1 W s9 n: i9 u
TinyXiong为新账户的密码,回车后,返回一个新账户。
9 S: T/ h$ t3 @( ]
这时我们查看账户列表:* S/ m3 m3 t( {; [
>eth.accounts. c* E2 _' P, Q+ |
/ t# F& n6 P. N, ~6 L, Y
可以看到账户数组你包含两个账户,新账户在第二个(索引为1)位置。0 L8 n0 [; w! C4 u& S( y9 w1 @
现在看看账户的余额:
; U1 A! H# E& s v4 Q$ v
>eth.getBalance(eth.accounts[1])- S4 `8 G/ }% K+ O2 x: \; {
' X$ x. i! e+ m' [
0) z" c8 P9 X: Y7 [. T' w
回车后,返回的是0,新账户是0。结果如:7 }( V0 C2 p# ~3 a2 w
& h5 }+ S- a+ P6 W0 B' L
给新账户转账# e: {- V+ w1 p% w9 h
5 ` X$ ~$ w. z9 p
我们知道没有余额的账户是没法部署合约的,那我们就从默认账户转1以太币给新账户,使用以下命令(请使用你自己eth.accounts对应输出的账户):1 ^/ f1 |4 x+ u& x# W
/ }9 b, C4 v9 b d
eth.sendTransaction({from:'0xb0ebe17ef0e96b5c525709c0a1ede347c66bd391',to:'0xf280facfd60d61f6fd3f88c9dee4fb90d0e11dfc',value:web3.toWei(1,"ether")})
在打开的tail-ftest.log日志终端里,可以同时看到挖矿记录9 e9 ]2 s2 ^0 F4 u
再次查看新账户余额,可以新账户有1个以太币
解锁账户8 y3 L5 l* T2 N2 l* S5 N5 T; }
在部署合约前需要先解锁账户(就像银行转账要输入密码一样),使用以下命令:+ S, p% j u; h# Z
personal.unlockAccount(eth.accounts[1],"TinyXiong");
“TinyXiong”是之前创建账户时的密码) V/ f; {% ~& k: i ~. L
5 e) `$ X6 ~8 G. [6 `' C. Q
解锁成功后,账户就准备完毕啦,接下来就是编写合约代码。; _& ^0 l! t2 ?% e1 ^% ~" r
# v& l; t; q/ E4 [$ ^8 Y+ p u
编写合约代码
现在我们来开始编写第一个智能合约代码,solidity代码如下:
pragmasolidity^0.4.18;( R8 i' @6 J6 L" P
& d& Q* i; E6 l! @4 ]% c4 i
contracthello{
stringgreeting;& k4 ]) s$ ], [& V6 C3 E( r
functionhello(string_greeting)public{% W! F) N' U' q6 [8 [* l
greeting=_greeting;* p* a; J. e; ~$ ^$ W) F) D2 I
}
functionsay()constantpublicreturns(string){, @" X; P. L. z+ o2 b& O
returngreeting;5 F0 ~. \' k5 B( }. G+ P9 `- ]
# v# V! m) r; o$ I- P" X
} `, g0 N4 q8 h% L/ c( b
- J+ O* Z' Y& p9 @
}2 |6 R1 _# |# [/ O" _; P
+ Q: w8 {# A. N9 S; q
简单解释下,我们定义了一个名为hello的合约,在合约初始化时保存了一个字符串(我们会传入helloworld),每次调用say返回字符串。
把这段代码写(拷贝)到Browser-Solidity,如果没有错误,点击Details获取部署代码,( }" {7 {. Q* r/ f+ @+ e, Z
6 a( E! @2 {+ w/ k
如
在弹出的对话框中找到WEB3DEPLOY部分,点拷贝,粘贴到编辑器后,修改初始化字符串为helloworld。
8 B+ X! O: U3 n! F' D3 `
solidity在博文写作时(2017/11/24),版本为0.4.18,solidity发展非常快,solidity版本之间有可能不能兼容,这是你可以在Browser-Solidity的Settings里选择对应的编译器版本。
Browser-Solidity也不停的更新中,截图可能和你看到的界面不一样。
部署合约1 @9 }: @' |" E# H
Browser-Solidity生成的代码,拷贝到编辑器里修改后的代码如下
5 U8 i6 G6 F; X n
var_greeting="HelloWorld";1 p- F }, e6 i4 ]. O+ `8 O. n; O
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"}]);
/ u( j) X) ^9 S9 g
varhello=helloContract.new(
) c9 {+ X% P( J5 x
_greeting,+ t: r5 \5 l# m
{
5 g1 I; p" [ Q. ]: f
from:web3.eth.accounts[1],
data:'0x6060604052341561000f57600080fd5b6040516102b83803806102b8833981016040528080518201919050508060009080519060200190610041929190610048565b50506100ed565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061008957805160ff19168380011785556100b7565b828001600101855582156100b7579182015b828111156100b657825182559160200191906001019061009b565b5b5090506100c491906100c8565b5090565b6100ea91905b808211156100e65760008160009055506001016100ce565b5090565b90565b6101bc806100fc6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063954ab4b214610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc61017c565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101725780601f1061014757610100808354040283529160200191610172565b820191906000526020600020905b81548152906001019060200180831161015557829003601f168201915b5050505050905090565b6020604051908101604052806000815250905600a165627a7a723058204a5577bb3ad30e02f7a3bdd90eedcc682700d67fc8ed6604d38bb739c0655df90029',
3 o4 J, `- ~) n' z0 m9 @; h
gas:'4700000'
},function(e,contract){
console.log(e,contract);3 a* P. Z1 Y$ b. m
: U+ _$ g5 w3 }7 l9 j
if(typeofcontract.address!=='undefined'){
console.log('Contractmined!address:'+contract.address+'transactionHash:'+contract.transactionHash);5 ^9 m; m* _7 u
% I* H; r, m3 ]7 j2 O
}0 ~* o2 j5 F# h4 u: y
$ q2 P0 N- Y; p
});* i% _8 ?/ G. @2 a1 C2 {- ?1 p
第1行:修改字符串为HelloWorld
第2行:修改合约变量名- S) v$ l7 H# P6 r
3 |. c& ]# w' \+ I# p5 f D
第3行:修改合约实例变量名,之后可以直接用实例调用函数。
% |9 \9 ?* m/ ]! {) ^, N
第6行:修改部署账户为新账户索引,即使用新账户来部署合约。8 ]9 z6 T( |: @& F, J
第8行:准备付的gas费用,IDE已经帮我们预估好了。
第9行:设置部署回调函数。. _6 a; H% f1 r- J, n# u. |3 O/ t& r0 ]7 D
. n8 H. a* ?3 Z1 u# G
拷贝回geth控制台里,回车后,看到输出如:
Contractmined!address:0x79544078dcd9d560ec3f6eff0af42a9fc84c7d19transactionHash:0xe2caab22102e93434888a0b8013a7ae7e804b132e4a8bfd2318356f6cf0480b3( l* \0 d; y. |- n
" s+ [/ t' S' R+ F1 u
说明合约已经部署成功。+ [3 J2 ]3 d) `$ t
在打开的tail-ftest.log日志终端里,可以同时看到挖矿记录* k7 P7 D/ G) A: e% ^6 \- K
3 e7 K+ ?# I! C; E- Y+ W
现在我们查看下新账户的余额:9 D% q0 z8 [7 m+ i! l, d, M6 f3 L
>eth.getBalance(eth.accounts[1])
是不是比之前转账的余额少呀!
) t$ }8 c7 S/ T! e, V: E. t7 F9 w0 s
运行合约1 W( h$ E I$ k+ w) v
; f0 j9 _8 v7 p3 ]3 L
>hello.say()! l5 c9 ^3 c+ j. t9 k/ S" ?6 c
3 e' {6 j% g- h7 d
"HelloWorld" O$ c6 } f4 a* G
输出HelloWorld,我们第一个合约HelloWorld,成功运行了。
运行截图如下:
. R$ q7 X7 ^" i/ O6 W
第一个合约的意义更重要的是体验智能合约开发流程,对于初学者一些可以选择先放弃一些细节,开发流程打通之后,可以增强信心进行下一步的学习。
作者:@xilibi2003
成为第一个吐槽的人