智能合约开发环境搭建及Hello World合约
945坏男人
发表于 2022-11-7 00:10:06
116
0
0
就先学习任何编程语言一样,入门的第一个程序都是HelloWorld。今天我们来一步一步从搭建以太坊智能合约开发环境开始,讲解智能合约的HelloWorld如何编写。
开发环境搭建
Solidity安装& K, ^1 I+ [; G$ d: ~
强烈建议新手使用Remix-SolidityIDE来进行开发。) m7 B+ f( u# z& q' K
; e6 P1 E) ^! p
Remix是一个基于浏览器的Solidity,就可以不用安装Solidity,本文的HelloWorld教程也将基于RemixSolidityIDE来进行。
如果你想自己安装请参考Solidity安装指引。& Z2 V& o& x% w/ ]& q
更新,开发环境搭建还可以看另一篇文章:搭建智能合约开发环境RemixIDE及使用。# t. j) F; D, G( @
geth安装; W, M2 V4 R8 `, p, w$ M
, l- p' V4 G$ w8 J/ x& U3 E
Mac下安装命令如下:其他平台参考:geth官方安装指引- L" P) J5 L# x5 m4 F$ D& Z
brewtapethereum/ethereum
" E8 x) V3 s6 Y% J- {
brewinstallethereum0 \; S+ V* t/ ~6 R, u
brew是Mac下的包管理工具,和Ubuntu里的apt-get类似5 f5 J7 u$ ]4 {8 h- D6 s
安装完以后,就是把geth控制台启动。) j! q/ o( x5 Z5 w' J6 t k
启动环境
在入门篇讲过,geth是一个以太坊客户端,现在利用geth启动一个以太坊(开发者)网络节点。 p) b' G7 n* ^9 E
geth--datadirtestNet--devconsole2>>test.log
0 k- ^; T( c. H4 b
执行命名后,会进入geth控制台,这时光标停在一个向右的箭头处,像这样
9 s& H4 G Z* b/ d- v& I' j4 {- t
命令参数说明
a# |% X2 B& ?! v
–dev启用开发者网络(模式),开发者网络会使用POA共识,默认预分配一个开发者账户并且会自动开启挖矿。4 z% E0 }1 Q9 w( b
/ E' e& P- P: e
–datadir后面的参数是区块数据及秘钥存放目录。
: B0 g$ r5 v4 a5 z p" d4 n/ B
第一次输入命令后,它会放在当前目录下新建一个testNet目录来存放数据。8 H$ P% X9 t1 F9 j
console进入控制台
, T1 i+ z2 s. {, B5 M
2>>test.log表示把控制台日志输出到test.log文件
/ |0 w6 B$ a5 ~
为了更好的理解,建议新开一个命令行终端,实时显示日志:
tail-ftest.log2 U& g7 a- N3 M2 o
/ C0 a& c* T1 v( O4 l
准备账户( l' p9 D% {0 Q h
8 D2 N2 `7 q r6 t2 l+ l1 ~
部署智能合约需要一个外部账户,我们先来看看分配的开发者账户,在控制台使用以下命令查看账户:# V0 s( y4 ?& P! k2 c
& R9 k# [2 q& a6 N/ \: A# F
>eth.accounts
回车后,返回一个账户数组,里面有一个默认账户,如:1 F8 ?. h8 _( I$ ^# ~
. m) J m( u G+ [( o4 s/ E. b- G( C
也可以使用personal.listAccounts查看账户,$ |' j3 U! x: Q! I I9 q
7 U* Y2 }) I) [) f- X) |
再来看一下账户里的余额,使用一下命令:
>eth.getBalance(eth.accounts[0])
**eth.accounts[0]**表示账户列表第一个账户+ B$ x2 T7 {# c/ h6 C! M
回车后,可以看到大量的余额,如:2 A6 G% W. s7 h z4 b
1.15792089237316195423570985008687907853269…e+77, b* k1 G s: z
9 Q8 h2 n F( `
开发者账户因余额太多,如果用这个账户来部署合约时会无法看到余额变化,为了更好的体验完整的过程,这里选择创建一个新的账户。
* T" |- F5 }6 c8 x: O! m% G6 E1 a& m* ^
创建账户" c3 c. n4 R @/ c7 x
使用以下命令创建账户:
>personal.newAccount("TinyXiong")
5 K: q9 w5 R* d' @* F
TinyXiong为新账户的密码,回车后,返回一个新账户。
- i5 Y+ N' |5 y% k: |1 @
这时我们查看账户列表:; V! G4 u9 v Y; Z- d8 {
8 U6 N3 i5 n. u8 j& U) h0 {7 x4 N
>eth.accounts
可以看到账户数组你包含两个账户,新账户在第二个(索引为1)位置。
. Q$ i( `/ M5 _- c$ f+ d
现在看看账户的余额:1 p8 t* C" e% L
>eth.getBalance(eth.accounts[1])- }! V4 @6 {7 a1 B
0* j5 I* ^ x7 C7 Y, |$ K0 C
6 X8 @" e1 h- F' W' r7 _
回车后,返回的是0,新账户是0。结果如:
给新账户转账" Z8 k( F4 _, s
我们知道没有余额的账户是没法部署合约的,那我们就从默认账户转1以太币给新账户,使用以下命令(请使用你自己eth.accounts对应输出的账户):
& e) i0 z' _: X. z6 E0 z
eth.sendTransaction({from:'0xb0ebe17ef0e96b5c525709c0a1ede347c66bd391',to:'0xf280facfd60d61f6fd3f88c9dee4fb90d0e11dfc',value:web3.toWei(1,"ether")})
; W, B2 K- E6 Z8 _( R
在打开的tail-ftest.log日志终端里,可以同时看到挖矿记录, ^# I' I$ K# l* G7 u; x
7 r# ~3 j4 v# ?: i% ]- p
再次查看新账户余额,可以新账户有1个以太币
解锁账户5 d! Q7 M5 |! f3 E7 L
在部署合约前需要先解锁账户(就像银行转账要输入密码一样),使用以下命令:
personal.unlockAccount(eth.accounts[1],"TinyXiong");; Q6 h/ w" k9 ]' l
“TinyXiong”是之前创建账户时的密码$ y5 w6 x6 q" B2 F& o1 i! U P
: Y; W U) E* O" Y' E6 Y( z* H( ]
解锁成功后,账户就准备完毕啦,接下来就是编写合约代码。9 A( q9 \$ U. b3 d; A" I8 [
编写合约代码
现在我们来开始编写第一个智能合约代码,solidity代码如下:
! p" X# ]2 N" v$ Z3 m/ Z; Y$ q. W
pragmasolidity^0.4.18;( r: T1 H: Q8 b7 o9 n
8 t- l- z( Z1 a0 P* z8 P
contracthello{
, f) E% E& K9 M S2 n
stringgreeting;! ]/ i& ?1 `8 M! z! ^9 _: L1 x
functionhello(string_greeting)public{( c: A3 _ v/ n4 }
greeting=_greeting;/ Q% u2 ~+ s' ]! R7 p+ |7 U
}. k c& x: J' V y% O
functionsay()constantpublicreturns(string){
returngreeting;
+ K+ r$ a% r3 @# `7 D) V
}
$ @. |5 x4 s; n, u6 U
}
- E+ ]: A( ]7 U
简单解释下,我们定义了一个名为hello的合约,在合约初始化时保存了一个字符串(我们会传入helloworld),每次调用say返回字符串。+ S3 q. F U9 |; }
. C8 K1 ]. F* w5 m% h0 A$ a U
把这段代码写(拷贝)到Browser-Solidity,如果没有错误,点击Details获取部署代码,
如
在弹出的对话框中找到WEB3DEPLOY部分,点拷贝,粘贴到编辑器后,修改初始化字符串为helloworld。& A! q6 r/ n) ]" P+ r" @% L% h6 y
. u, U) ]8 \$ n/ q2 M
solidity在博文写作时(2017/11/24),版本为0.4.18,solidity发展非常快,solidity版本之间有可能不能兼容,这是你可以在Browser-Solidity的Settings里选择对应的编译器版本。
Browser-Solidity也不停的更新中,截图可能和你看到的界面不一样。! W- b7 J3 m8 c7 A) U( k: K
9 A7 i# u1 m* g8 a, ~
部署合约
, D% h! h6 K/ S
Browser-Solidity生成的代码,拷贝到编辑器里修改后的代码如下) ^$ V( Q) [/ u$ I
var_greeting="HelloWorld";/ X& p u* X" ^/ @7 @6 N
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"}]);: l1 |! f5 _) k# g( @
varhello=helloContract.new(
_greeting,
5 U5 {* D" ^" g) [9 H# b* J
{2 L7 E4 f8 n, q7 b3 f' M% b
from:web3.eth.accounts[1],
data:'0x6060604052341561000f57600080fd5b6040516102b83803806102b8833981016040528080518201919050508060009080519060200190610041929190610048565b50506100ed565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061008957805160ff19168380011785556100b7565b828001600101855582156100b7579182015b828111156100b657825182559160200191906001019061009b565b5b5090506100c491906100c8565b5090565b6100ea91905b808211156100e65760008160009055506001016100ce565b5090565b90565b6101bc806100fc6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063954ab4b214610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc61017c565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101725780601f1061014757610100808354040283529160200191610172565b820191906000526020600020905b81548152906001019060200180831161015557829003601f168201915b5050505050905090565b6020604051908101604052806000815250905600a165627a7a723058204a5577bb3ad30e02f7a3bdd90eedcc682700d67fc8ed6604d38bb739c0655df90029',
gas:'4700000'6 H$ z, r7 R3 y8 D3 F% s
5 t1 o" O( i; v2 J0 \ ]/ H
},function(e,contract){
console.log(e,contract);# v) F. j3 b$ h0 f# r8 V
/ L- k3 w/ Z3 L: h; h; j
if(typeofcontract.address!=='undefined'){
console.log('Contractmined!address:'+contract.address+'transactionHash:'+contract.transactionHash);
}( p0 p% I" _1 M7 \1 V/ X3 M# ?7 X* F l
});
& J& T2 H! }: o( C3 M c- e
第1行:修改字符串为HelloWorld0 K# S: Z- E! G& ?
第2行:修改合约变量名
2 v2 D; y" E+ K! Z. a( V" v
第3行:修改合约实例变量名,之后可以直接用实例调用函数。2 u5 X+ |. E! ^8 t" W4 n, r
第6行:修改部署账户为新账户索引,即使用新账户来部署合约。( e6 l4 V$ j+ u4 j2 b' S
第8行:准备付的gas费用,IDE已经帮我们预估好了。3 s2 ]4 `7 ]7 t U8 N/ m" _
* Y/ X6 y" U: u7 I* e/ d
第9行:设置部署回调函数。
, C* M- c) c) D: G2 P" F2 y
拷贝回geth控制台里,回车后,看到输出如:# V0 C6 p+ R5 d/ Q( ^
Contractmined!address:0x79544078dcd9d560ec3f6eff0af42a9fc84c7d19transactionHash:0xe2caab22102e93434888a0b8013a7ae7e804b132e4a8bfd2318356f6cf0480b3
说明合约已经部署成功。
: z& p4 `9 K2 I4 q
在打开的tail-ftest.log日志终端里,可以同时看到挖矿记录. n: A8 _ W) d! a
现在我们查看下新账户的余额:* {; W2 @7 r- W8 s3 |/ i
>eth.getBalance(eth.accounts[1])8 c5 q% |: Z7 W m4 `! f
' h! J( i$ l& C8 y K) J3 v( D" L- c
是不是比之前转账的余额少呀!
0 e9 m# G" @* n Z1 Z/ S+ K. U$ ~* d
运行合约5 t: P6 d- X/ c3 B6 H3 p$ a! f c
>hello.say()% Z+ V% T8 D- y, |/ l
"HelloWorld" M& _/ S/ f' u8 V
输出HelloWorld,我们第一个合约HelloWorld,成功运行了。3 U+ p# C) K& z$ [
* i% w( O' W: Y! r- o2 M1 \: Z
运行截图如下:
第一个合约的意义更重要的是体验智能合约开发流程,对于初学者一些可以选择先放弃一些细节,开发流程打通之后,可以增强信心进行下一步的学习。
作者:@xilibi2003
成为第一个吐槽的人