智能合约开发环境搭建及Hello World合约
945坏男人
发表于 2022-11-7 00:10:06
245
0
0
9 _! @6 g, z2 S7 q4 @) u$ v
就先学习任何编程语言一样,入门的第一个程序都是HelloWorld。今天我们来一步一步从搭建以太坊智能合约开发环境开始,讲解智能合约的HelloWorld如何编写。. D0 I: H$ B M- P
' o# `/ M6 `: P" l. b* D
开发环境搭建, D+ P9 e* _4 s2 b; e) x% j
8 F: w0 T8 z0 U# e3 ^* J4 N- n
Solidity安装3 G7 [2 l# U. T; E b
强烈建议新手使用Remix-SolidityIDE来进行开发。
$ e& J; s1 f; B/ Q/ G
Remix是一个基于浏览器的Solidity,就可以不用安装Solidity,本文的HelloWorld教程也将基于RemixSolidityIDE来进行。
0 E: c( j7 V' V7 @* v
如果你想自己安装请参考Solidity安装指引。' {4 G* H7 m5 Z; ~( @ [) R
更新,开发环境搭建还可以看另一篇文章:搭建智能合约开发环境RemixIDE及使用。; m9 a5 x9 O# m: ]& }8 f7 }6 e6 j
geth安装
Mac下安装命令如下:其他平台参考:geth官方安装指引2 D, K8 h& [1 }: v& S- B
brewtapethereum/ethereum
6 A" b" a" o B2 _* I) X0 V
brewinstallethereum$ z8 _7 `3 U! p- \
" d' x( ]& ?' D1 r( S
brew是Mac下的包管理工具,和Ubuntu里的apt-get类似7 Y' T0 O9 ]0 F- g( L" ~
% n3 J; F* X5 W8 F% P+ r3 [0 |2 A8 Q
安装完以后,就是把geth控制台启动。
+ W7 R% ^# E+ V$ t
启动环境
: x0 U! {! I+ u9 u/ G& `, P+ b
在入门篇讲过,geth是一个以太坊客户端,现在利用geth启动一个以太坊(开发者)网络节点。: i- u' l4 O% D6 H* [
P$ u* D/ f2 f4 G" y
geth--datadirtestNet--devconsole2>>test.log
执行命名后,会进入geth控制台,这时光标停在一个向右的箭头处,像这样6 r8 P! s1 K. B8 d
5 ~; W/ l+ Z" o* C) d* c N
命令参数说明
: ^3 O/ [) E4 t8 r' y4 \+ d! L" Q
–dev启用开发者网络(模式),开发者网络会使用POA共识,默认预分配一个开发者账户并且会自动开启挖矿。
1 D6 b" y: J; x. r
–datadir后面的参数是区块数据及秘钥存放目录。
第一次输入命令后,它会放在当前目录下新建一个testNet目录来存放数据。* X1 w- k8 `/ h$ _, u
console进入控制台4 p; a# t& d! U& j5 B% B9 t
7 }3 v: a) F6 b8 C, x, W9 c3 U1 `
2>>test.log表示把控制台日志输出到test.log文件
为了更好的理解,建议新开一个命令行终端,实时显示日志:
tail-ftest.log9 y3 ~+ J7 g4 y4 t
准备账户/ U0 Z! @& }9 r% r0 A
& d% ~/ ]* R1 N% ]9 i( m
部署智能合约需要一个外部账户,我们先来看看分配的开发者账户,在控制台使用以下命令查看账户:$ v( S; Z# K# M8 ?9 G
7 [. t! P& E+ J. ^( F! V# [! Z
>eth.accounts
回车后,返回一个账户数组,里面有一个默认账户,如:; J4 ^. p4 S" u9 p8 F5 ~! e/ D
也可以使用personal.listAccounts查看账户,
1 x" r: w+ c% {0 u: _; x* o" J
再来看一下账户里的余额,使用一下命令:
>eth.getBalance(eth.accounts[0])! \4 K' W. @; }4 J( c5 o
**eth.accounts[0]**表示账户列表第一个账户# l; T9 U7 B/ d$ H2 H
" b$ S( S2 F: L9 W, Q; Y
回车后,可以看到大量的余额,如:
1.15792089237316195423570985008687907853269…e+77# k( M2 r7 n* X+ G
% {, J+ a; `8 Q8 [8 ?! D
开发者账户因余额太多,如果用这个账户来部署合约时会无法看到余额变化,为了更好的体验完整的过程,这里选择创建一个新的账户。
创建账户7 v) V9 I5 m' c" j2 _
9 r; \0 T4 v4 i5 n; G: |0 ^
使用以下命令创建账户:
>personal.newAccount("TinyXiong")5 G- S- |8 n. _5 T8 @
TinyXiong为新账户的密码,回车后,返回一个新账户。( F2 E; ~' F0 Q8 d
* f$ r8 U- p) X. Y G- Z
这时我们查看账户列表:
>eth.accounts! b7 `) c! q. @. i* {1 u0 O
可以看到账户数组你包含两个账户,新账户在第二个(索引为1)位置。3 T3 ? i8 G* m& ~) v$ }
现在看看账户的余额: j6 h6 b: ]7 v- L3 V4 X
>eth.getBalance(eth.accounts[1])/ |1 M! m6 I" H: D: r) X8 n
' f2 ~( _% |: h: U; }
0
回车后,返回的是0,新账户是0。结果如:
- s2 ?9 b1 \" J: `' x
给新账户转账5 b& f" H, m& F& S4 G+ J2 l. F4 v
我们知道没有余额的账户是没法部署合约的,那我们就从默认账户转1以太币给新账户,使用以下命令(请使用你自己eth.accounts对应输出的账户):
eth.sendTransaction({from:'0xb0ebe17ef0e96b5c525709c0a1ede347c66bd391',to:'0xf280facfd60d61f6fd3f88c9dee4fb90d0e11dfc',value:web3.toWei(1,"ether")})8 t! T# w5 I# h2 h; |. v
( y |- R6 Y( m. Z; z7 F4 }9 K
在打开的tail-ftest.log日志终端里,可以同时看到挖矿记录/ y+ P o$ _1 h' R3 O: J6 S# N' d
再次查看新账户余额,可以新账户有1个以太币
0 g# |" n" F- A
解锁账户) l9 }6 B/ m1 L; Z* Q/ F" Z) {
在部署合约前需要先解锁账户(就像银行转账要输入密码一样),使用以下命令:2 i# j8 @0 \6 M9 {
5 F( R1 s; J$ {+ G5 i& v
personal.unlockAccount(eth.accounts[1],"TinyXiong");
) M" ]5 {! J0 Z! H& ?2 _9 F
“TinyXiong”是之前创建账户时的密码
" a$ p0 N5 {7 d `0 i+ {
解锁成功后,账户就准备完毕啦,接下来就是编写合约代码。3 c% r$ ?% |0 C% }
& O4 m0 R* j' A4 n# y# S9 y/ j V
编写合约代码
% b7 d2 ]* a7 w$ ~- {$ f, f
现在我们来开始编写第一个智能合约代码,solidity代码如下:8 K9 X6 t7 X" u: |/ K
pragmasolidity^0.4.18;
+ A$ T4 j5 i, Q# X0 W1 F7 ^: b2 S T
contracthello{# d- n0 N: T4 F \& [
/ L0 [, G$ N- h0 ]/ R0 f% C% X
stringgreeting;( _. a2 d, d8 y; o4 E" m* Y
$ A2 h* q0 d9 ^8 p! R% V5 W
functionhello(string_greeting)public{9 k, [) P( x2 _+ U+ F7 [9 Q( ] |
greeting=_greeting;
3 M& g `) O) m+ h/ }( u3 o6 k* S$ ~0 M4 R
}" W2 M( C# D( |; c3 \
! N. X$ P) C2 f0 L
functionsay()constantpublicreturns(string){) {( S. }1 T. M3 q' B
* D+ U' m" B7 m9 J
returngreeting;( A# P) _8 m; _* o6 j) f# x$ N( L" P
}& w4 `* h$ D9 y- }+ Z; {: O4 j
& [$ P: K$ ]6 j
}
简单解释下,我们定义了一个名为hello的合约,在合约初始化时保存了一个字符串(我们会传入helloworld),每次调用say返回字符串。/ S) i/ ~4 X$ z* D/ U3 p+ |, t* Y
把这段代码写(拷贝)到Browser-Solidity,如果没有错误,点击Details获取部署代码,2 S1 j$ b+ Z2 J
: @' S- d, a: j0 U) T6 F
如
在弹出的对话框中找到WEB3DEPLOY部分,点拷贝,粘贴到编辑器后,修改初始化字符串为helloworld。4 D; v6 e+ b, ?# \& w b7 P
2 z1 c) c* {2 X( X5 |) m
solidity在博文写作时(2017/11/24),版本为0.4.18,solidity发展非常快,solidity版本之间有可能不能兼容,这是你可以在Browser-Solidity的Settings里选择对应的编译器版本。
" @% m' \! S+ S4 c: T
Browser-Solidity也不停的更新中,截图可能和你看到的界面不一样。
部署合约( B$ r* s' Z# i* g% K$ O, r- b
Browser-Solidity生成的代码,拷贝到编辑器里修改后的代码如下* G E# `( t C* u& B
# \( q P/ A( ]
var_greeting="HelloWorld";5 l/ A$ s4 p1 s2 }" ]
. S& R, d4 d& Q) k7 T z2 C( l
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"}]);
varhello=helloContract.new(% O& W, X6 s+ R# w$ f) B/ U
3 m0 D4 b% Z- l1 ]5 {# S
_greeting,9 h7 }, D- E A& Q R M
! r: J2 H& z* @7 }2 F
{
from:web3.eth.accounts[1],
data:'0x6060604052341561000f57600080fd5b6040516102b83803806102b8833981016040528080518201919050508060009080519060200190610041929190610048565b50506100ed565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061008957805160ff19168380011785556100b7565b828001600101855582156100b7579182015b828111156100b657825182559160200191906001019061009b565b5b5090506100c491906100c8565b5090565b6100ea91905b808211156100e65760008160009055506001016100ce565b5090565b90565b6101bc806100fc6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063954ab4b214610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc61017c565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101725780601f1061014757610100808354040283529160200191610172565b820191906000526020600020905b81548152906001019060200180831161015557829003601f168201915b5050505050905090565b6020604051908101604052806000815250905600a165627a7a723058204a5577bb3ad30e02f7a3bdd90eedcc682700d67fc8ed6604d38bb739c0655df90029',' j: m5 M9 m+ |6 ~6 }
gas:'4700000'' |5 u6 q! Z# O: w8 d9 C
" z- x7 B1 ?: ]2 N
},function(e,contract){0 K' `* {4 k$ T' R8 p
' A8 x9 K3 m5 W+ c7 ]' l
console.log(e,contract);
if(typeofcontract.address!=='undefined'){& \- m: R" e8 b2 ~( t
console.log('Contractmined!address:'+contract.address+'transactionHash:'+contract.transactionHash);2 I* p& R0 k# }- T
}
; e& t$ E5 z6 c
});
3 `6 k" J" a1 v
第1行:修改字符串为HelloWorld( |# w1 q7 s+ u8 G8 d# O7 j7 Y' q# V
第2行:修改合约变量名
! \) P1 U j/ n' p$ W
第3行:修改合约实例变量名,之后可以直接用实例调用函数。3 l6 O( j( r7 @- C
8 F2 ?5 J- ?) c+ u$ i7 W# p$ C
第6行:修改部署账户为新账户索引,即使用新账户来部署合约。
第8行:准备付的gas费用,IDE已经帮我们预估好了。" R3 E( H7 `0 {: y& B3 U
. T& N) h" O7 R3 H& S0 G. i
第9行:设置部署回调函数。, I' _6 ~0 Y4 S$ ~
' o# o1 D- \ n2 C- Y
拷贝回geth控制台里,回车后,看到输出如:
Contractmined!address:0x79544078dcd9d560ec3f6eff0af42a9fc84c7d19transactionHash:0xe2caab22102e93434888a0b8013a7ae7e804b132e4a8bfd2318356f6cf0480b3* }' z0 q% }+ C6 H- a; S X9 L( B
8 }; y7 r7 r: t/ N1 o9 R$ K
说明合约已经部署成功。5 k' i0 l1 v$ [: W- N
在打开的tail-ftest.log日志终端里,可以同时看到挖矿记录
现在我们查看下新账户的余额:5 ?- L) o7 x+ S- {. P
, h7 Q- K* t7 E; r: e9 Q, e
>eth.getBalance(eth.accounts[1])
是不是比之前转账的余额少呀!: L5 ^' B" y! ]1 q0 D2 {; c
运行合约# {4 H% K" R5 u7 E# e
5 }3 M" W; N q% S5 k) U' @
>hello.say(): R2 }9 Z+ o2 f; {7 O' N- ^" o
"HelloWorld"8 M) e- O# C8 r- s9 v: d
输出HelloWorld,我们第一个合约HelloWorld,成功运行了。5 u* c9 U( \% _ T
运行截图如下:8 |0 ~ E9 k. a' n& {% R
9 D! C/ y3 b; l
第一个合约的意义更重要的是体验智能合约开发流程,对于初学者一些可以选择先放弃一些细节,开发流程打通之后,可以增强信心进行下一步的学习。
7 c/ r0 p( ]: l; |' M
作者:@xilibi2003
成为第一个吐槽的人