以太坊教程:搭建环境、编写编译一个智能合约
dancing520
发表于 2022-11-6 21:10:54
707
0
0
以太坊是什么
以太坊(Ethereum)是一个开源的有智能合约功能的公共区块链平台。通过其专用加密货币以太币(Ether)提供去中心化的虚拟机(“以太虚拟机”EthereumVirtualMachine)来处理点对点合约。! m- Y- M, Z1 I
以太坊的概念首次在2013至2014年间由程序员VitalikButerin,受比特币启发后提出,大意为“下一代加密货币与去中心化应用平台”,在2014年通过ICO众筹得以开始发展。目前以太币是市值第二高的加密货币,仅次于比特币。
. I' j5 G0 P5 K% a" E" o7 J
以太坊区块链是什么?
3 W5 I0 ~! P/ g: z7 ^2 Q4 `
以太坊区块链有2个主要组件:* c$ I/ Q0 \. p7 ?4 W- P3 q
( n5 y3 }# @3 M
数据存储:网络中每笔交易都存储在区块链上。当你部署合约时,就是一笔交易。当你执行合约功能时,也是另一笔交易。所有的这些交易都是公开的,每个人都可以看到并进行验证。这个数据永远也无法篡改。为了确保网络中的所有节点都有着同一份数据拷贝,并且没有向区块链中写入任何的无效数据,以太坊使用一个叫做工作量证明的算法来保证网络安全。
* W4 d* F: r" |' E8 B/ }* W8 L+ m
代码:就数据的层面而言,区块链就是存储交易。在以太坊的世界里,你可以通过一个叫Solidity的语言编写逻辑/应用代码(也就是智能合约)。然后用solidity编译器将代码编译为以太坊字节码,并将字节码部署到区块链上(也有一些其他的语言可以写合约,不过solidity是到目前为止用得最多也是相对更容易的选择)。所以,以太坊不仅仅会存储交易数据,它还会存储和执行智能合约代码。) Y% o7 y( |# V* t6 N( p# j
2 n( E4 m0 S D: |
可以简单的理解以太坊区块链的作用就是存储数据和代码,并在EVM(EthereumVirtualMachine,以太坊虚拟机)中执行代码。* V% X% }2 @/ G2 s1 t3 o
' c$ c) ?9 n, g! H# x3 L) J
要准备的基础知识
' p# B' A5 {0 \0 R% ^: L+ D I" F
为了进行以太坊开发,你应该对以下语言/技术有基本了解:+ V; h- T: `8 a
0 _ V1 h+ z( t! ^$ a
熟悉某种面向对象语言(如Python,Java,go)
HTML/CSS/Javascript" j& Y- v7 M) e+ w. M
基本的命令行交互如Linuxshell命令9 U8 I) K& Y3 }6 m* T
! s7 t6 ~- Q8 S ]
理解数据库的基本概念% }: Q2 R7 H# P* t! C9 F$ E2 T
为了构建以太坊去中心化应用即Dapp(Decentralizedapplication),以太坊有一个非常方便的JavaScript库即web3.js,你也可以在一些js框架中直接引入该库构建应用,比如react,angular,vue等。4 n- n3 o& i/ y7 H7 X
3 ?. f0 j; g7 f7 J
示例:一个以太坊投票应用9 s. V& k/ h5 @$ n$ k/ z
0 P; g; c$ g( J, u0 `
以太坊教程示例中,我们将会构建一个简单的去中心化投票应用。所谓去中心化应用,就是一个不只存在于某一中心化服务器上的应用。在网络中成百上千的电脑上,会运行着非常多的应用副本,这使得它几乎不可能出现宕机的情况。你将会构建一个投票应用,在这个应用中,你可以初始化参与选举的候选者,并对候选者投票,而这些投票将会被记录在区块链上。你将会经历编写投票合约,部署到区块链并与之交互的整个过程。你将会了解什么是一个合约,将合约部署到区块链上并与之交互意味着什么。# e" ~* @; u' u& Q8 y4 i; y
- I& X$ O1 a* Y5 u
本质上,区块链就像是一个分布式数据库,这个数据库维护了一个不断增长的记录链表。如果熟悉关系型数据库,你应该知道一张表里有很多行的数据。现在,对数据进行批(batch)量处理(比如每批100行),并将每个处理的批次相连。就可以形成一个区块链了!在区块链里,每个批次的数据就叫一个块(block),块里的每一行就叫一笔交易(transaction)。 c! C5 Y$ t( x- h; X, ]7 i
现在,你对以太坊已经有了基本了解,我们可以开始构建投票的dapp了。这将会加强你对以太坊的认识,并且初略了解以太坊的功能。
以太坊开发环境搭建
Linux
+ u7 I! D. ~, ?1 _
示例是Ubuntu16.04下的学习环境搭建,你只需要成功安装了nodejs和npm,就可以继续项目的下一步了。
, R& n" T0 V9 n% B2 i
我们通过npm安装ganache和web3包来为以太坊教程提供支撑。我们也需要安装solc来编译合约。4 W: m% x4 j$ I$ W" `
1 D) w) [* Z m2 e3 X$ t4 r0 e
下面是安装过程:# b( o" Q* h" x' ]' f! v
' h1 y' `% E# V' T3 w- W
$sudoapt-getupdate
" O" i8 V, m( {+ b, @6 t
$curl-sLhttps://deb.nodesource.com/setup_7.x-onodesource_setup.sh
$sudobashnodesource_setup.sh9 \" @, E) O+ h( S% {
: @9 Z, b5 \. L: s' f. D0 c
$sudoapt-getinstallnodejs- Y) A' L4 F" u# t
; e7 r% `2 {, s( w! C0 K- v
$node--version
v7.4.09 s1 K( x# \, C) ?" l! a
# K" M ]& i, e+ ~; R
$npm--version
+ ^8 A2 Z5 G M" F
4.0.5' t4 \( S) f. Z
$mkdir-pethereum_voting_dapp/chapter1& i' Y! ]; s( T* N# U3 l3 Q
" i* @( |2 r" F+ ^: l+ f
$cdethereum_voting_dapp/chapter1
6 z! A& J1 {7 V5 x9 w' I# {
$npminstallganache-cliweb3@0.20.1solc
$node_modules/.bin/ganache-cli# C/ z+ A. t& E
如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到下面的输出。$ I+ G9 b. A5 d8 N3 ]1 L C+ w% Z, f
; h% D# q( q7 }8 O4 ~) J6 T
GanacheCLIv6.0.3(ganache-core:2.0.2)
1 I! w% b0 j7 J( x/ m
AvailableAccounts! R* }5 ~; m8 F. Y7 i. K' a6 [5 ]. K
==================7 i, @& L: Y& H3 {7 H% a, A/ c
# u% B* S" V7 ^+ B) O
(0)0x5c252a0c0475f9711b56ab160a1999729eccce973 s- i1 F! d- k, N( ]! r( G
* n8 S3 `; ~+ V& [- ?7 ?) B, g
(1)0x353d310bed379b2d1df3b727645e200997016ba3
(2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23
(3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5$ F9 n- X! t/ ~
$ I# X/ { } j/ G" W6 Y* `, ^
(4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798
(5)0xda695959ff85f0581ca924e549567390a0034058 Z% @6 e! C9 G5 e% @8 w4 c2 b
(6)0xd4ee63452555a87048dcfe2a039208d1133237908 W1 s6 `0 @; j+ v2 @
(7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14: P( C# d' }! W% }
6 e9 N% {. k$ t5 `
(8)0xba7ec95286334e8634e89760fab8d2ec1226bf42% v% Q0 {0 i7 O
(9)0x208e02303fe29be3698732e92ca32b88d80a2d36" }9 G/ j( N# G* o7 K2 [+ M
* d) n5 H: ^# Q
PrivateKeys
==================
(0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b# T) z: q( M: a3 d1 I' H
(1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603
) H9 I1 I% i4 n0 |, G
(2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99/ G4 ^& K) k% k' @
(3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f35430
- u, a1 t0 F% U2 f# a! Y
(4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a8
; |2 _5 K `/ h+ W- y) k
(5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc, [! u2 k% L+ W0 r, V
(6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a9
1 U1 D, B( D* q$ @1 T3 S8 i/ s
(7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d
(8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a
(9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0
HDWallet! z$ y4 X5 X& s# b0 H# r
8 i3 s0 k1 d/ V+ b* a
==================. e3 k9 e; }- _( U: Q5 d5 w
Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella
+ D4 E# ]0 N" y/ S! y* f8 a2 d# _
BaseHDPath:m/44'/60'/0'/0/{account_index}
Listeningonlocalhost:8545
为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。
MacOS( A/ Y9 g5 |5 K: \7 |- m# T& p9 m2 m( D
* }5 k! G% I9 h" d6 }1 q+ J7 }
如果你还没有安装homebrew,请按照https://brew.sh/的指示安装homebrew。homebrew是一个包管理器,它可以帮助我们安装开发所需的所有其他软件。按照下面的指示安装所有其他所需的包。* u1 Q8 ` ]& y) H
$brewupdate
$brewinstallnodejs3 M. f. X5 R) k$ h2 @! `$ q& s
$node--version" f7 J. q& c& X# z8 l, S
v7.10.0- V0 I s, @1 Z9 y/ O: F. Z
- H8 p6 |$ m- P9 I- ~& ?0 o) c0 A* J
$npm--version
6 |1 R( A' }8 Y
4.2.09 {' t4 w Q5 y0 W4 e* e9 s
( `, O& g( \' j2 c
$mkdir-pethereum_voting_dapp/chapter1! k; ~$ K, b4 s# k6 w
7 }6 i4 E% T' ]0 K# `6 m) L3 I: y: z. y
$cdethereum_voting_dapp/chapter17 C5 q# T1 n3 X3 M8 t
$ C) T, ^- M9 Q! C( @
$npminstallganache-cliweb3@0.20.1solc
$node_modules/.bin/ganache-cli- ]+ y }' Y0 _0 M" }) T
/ \1 R5 x. {+ y5 X7 U' \
我们通过npm安装ganache和web3包。我们也需要安装solc来编译合约。
如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到右图所示的输出。7 E& ^4 ?+ H: I0 V4 L3 g
( y! w' \4 G# F4 G, y* A6 N
GanacheCLIv6.0.3(ganache-core:2.0.2) I' [& i$ b" p! \: j$ _
# {5 E! s& j# m0 L8 }" X
AvailableAccounts
" O4 k5 ^8 L' U3 ?
==================
(0)0x5c252a0c0475f9711b56ab160a1999729eccce974 \: T# A3 m! y" G, M n
* w7 K) X5 T6 D4 d- Q4 \" @5 u0 b5 ?
(1)0x353d310bed379b2d1df3b727645e200997016ba38 K- z8 B: z6 a+ t
(2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23
% e% M3 I" J: F" e) V( p
(3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5
(4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798
$ b' N+ R8 P% \% H3 \' F" i9 Y. h1 D: B
(5)0xda695959ff85f0581ca924e549567390a0034058
5 R7 k+ c& ]3 V" ]# ?& T
(6)0xd4ee63452555a87048dcfe2a039208d113323790; l$ O/ m0 A% \! V4 f( g( ]
(7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d147 e( |5 q3 h3 k* _7 E% X* j
(8)0xba7ec95286334e8634e89760fab8d2ec1226bf425 @( a; M* Z3 I
* W7 C9 H6 _0 {
(9)0x208e02303fe29be3698732e92ca32b88d80a2d36& ^* J* d8 v2 J# z5 W9 `/ V
PrivateKeys# G. ~9 W5 z7 f2 [- z3 A) t: K/ f! \& G
==================, b0 w' Q; T q2 b
(0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b
0 ^1 R* v ]3 S3 _" \, B% F8 Q: Q
(1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603
/ b* o" D( u' [0 {$ e+ @3 [
(2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99, `8 \/ b/ J, T" _ v
(3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f354302 Q/ |; [, f, D' ~2 o6 J! j
(4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a80 n O) g( z# c7 S
(5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc
, m1 Q2 d1 }& y6 G) n
(6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a9
2 }2 e! t7 [) Q( S# s
(7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d1 w/ e, y/ w1 N: k5 I" ~* f, ~
(8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a
(9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0& k8 ^/ d9 j" p+ y8 w# x
HDWallet0 M: W6 A- C4 ?# F
==================" w1 L, Y; c2 L% l# Y" d2 s" C
, r9 R8 J. _2 m) Q9 ? M0 X
Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella! l7 x" l) u2 J) H3 g9 n2 j3 \
BaseHDPath:m/44'/60'/0'/0/{account_index}
Listeningonlocalhost:8545
( A2 p/ e3 d6 s$ Q$ F9 ^# h
为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是以太坊账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。
Windows, k+ ~: l# v, H" B
" {3 B8 z1 q7 I+ y8 w1 \- A% p
安装VisualStudioCommunityEdition。如果你选择定制安装,那么至少应该安装VisualC++(目前的版本是VS2017)
, x1 S& z( `+ r
安装WindowsSDKforWindows5 r" p1 y4 p9 z+ _2 [$ k3 K% x
安装Python2.7如果你还没有安装的话,并且确保将它加入到环境变量PATH
- K' F0 r7 L+ O6 L1 Y, b, i1 d
安装git如果你还没有安装并加入到PATH
& B" m8 Y9 I2 Q3 \4 {" L
安装OpenSSL。确保选择了正确的安装包,并且只安装完整版(而不是轻装版)。你必须将OpenSSL安装到推荐安装的位置–不要改变安装路径- g7 R3 X, V, J8 j4 t+ p* d' r
下载和安装nodev8.1.2。不推荐使用版本v6.11.0搭配VS2017
! ]6 E7 D: Y- l; ^( X$ R0 ]
执行命令npminstallganache-cliweb3@0.20.1solc
m) F- X. g: s* K* U
SolidityContracts' R7 I) ~% ~% x6 S4 Z$ W. P6 b3 U
现在已经安装好ganache并运行,我们将会开始编写第一个以太坊智能合约。
% c+ M+ o( H* A: c! ~$ x
我们会使用solidity编程语言来编写合约。如果你熟悉面向对象编程,学习用solidity写合约应该非常简单。我们会写一个叫做Voting的合约(可以把合约看成是面对对象编程语言的一个类),这个合约有以下内容:# ^8 a. B+ d* H+ L
一个构造函数,用来初始化一些候选者。
% H/ C z/ v4 B
一个用来投票的方法(对投票数加1)* p, d ^2 b* L; Y8 N5 y8 v
一个返回候选者所获得的总票数的方法
2 ^6 x, D/ Z" B8 o# ?
当你把合约部署到区块链的时候,就会调用构造函数,并只调用一次。与web世界里每次部署代码都会覆盖旧代码不同,在区块链上部署的合约是不可改变的,也就是说,如果你更新合约并再次部署,旧的合约仍然会在区块链上存在,并且数据仍在。新的部署将会创建合约的一个新的实例。
4 `6 E) t1 `( M
pragmasolidity^0.4.18;2 C/ S# L$ |- Q3 w
/ o/ v0 ^' ~+ L: `; m6 ~, n
contractVoting{
mapping(bytes32=>uint8)publicvotesReceived;
+ l% U4 a& d8 a5 [* L+ ~
bytes32[]publiccandidateList;
functionVoting(bytes32[]candidateNames)public{
) a( s" Q* E+ @4 u. v7 T$ t
candidateList=candidateNames;2 Q/ \' L. g# C- q2 {: f
}+ O4 l1 n9 Q5 Y x+ D6 L
' I$ p/ }- Q3 U, j! y
functiontotalVotesFor(bytes32candidate)viewpublicreturns(uint8){
6 U8 a2 v7 L+ f, z. G& h; o
require(validCandidate(candidate));' n2 D0 d8 G/ T& T6 q" G# k
returnvotesReceived[candidate];3 X# Q: v! X" N5 @1 a3 m' T. f4 c
}6 j7 Q w# n8 F, N- D9 S( {4 M
functionvoteForCandidate(bytes32candidate)public{1 S$ h" e0 a6 v
: D( B0 r6 W6 ]$ g
require(validCandidate(candidate));* ^( b- X/ Z1 V) c& o* N( B
votesReceived[candidate]+=1;% p9 X: M0 V. V: V- Z
6 E) Z1 _$ w5 x8 J
}8 _3 K* W m8 ?' E* S% e) ` G$ e
7 o O, ]8 x4 K8 F
functionvalidCandidate(bytes32candidate)viewpublicreturns(bool){8 s0 f! ~# j: }
* T7 M! B8 L. I& N5 W
for(uinti=0;i
将右侧代码拷贝到一个叫做Voting.sol的文件中,并保存到chapter1目录下面。
3 z( k! G7 ]9 e3 t2 f
代码和解释1 s, P; j, l: }: @5 }4 t1 b6 l
Line1.我们必须指定代码将会哪个版本的编译器进行编译, K% ]; x+ }4 e$ a* d1 w4 B
0 ] O e- r7 K7 q
Line3.mapping相当于一个关联数组或者是字典,是一个键值对。mappingvotesReceived的键是候选者的名字,类型为bytes32。mapping的值是一个未赋值的整型,存储的是投票数。( Q- O3 B: x5 O+ G; v; W( u' G
; [- O# I Y& [# K4 Z% b( p
Line4.在很多编程语言中,仅仅通过votesReceived.keys就可以获取所有的候选者姓名。但是,但是在solidity中没有这样的方法,所以我们必须单独管理一个候选者数组candidateList。
* S& D* R! m p% E
Line14.注意到votesReceived[key]有一个默认值0,所以你不需要将其初始化为0,直接加1即可。9 v% m" N, K2 T# j( K1 V. o$ G% q
你也会注意到每个函数有个可见性说明符(visibilityspecifier)(比如本例中的public)。这意味着,函数可以从合约外调用。如果你不想要其他任何人调用这个函数,你可以把它设置为私有(private)函数。如果你不指定可见性,编译器会抛出一个警告。最近solidity编译器进行了一些改进,如果用户忘记了对私有函数进行标记导致了外部可以调用私有函数,编译器会捕获这个问题。这里可以看到所有的可见性说明符。
0 e2 X2 E, f/ F5 [) o6 z/ D
你也会在一些函数上看到一个修饰符view。它通常用来告诉编译器函数是只读的(也就是说,调用该函数,区块链状态并不会更新)。所有的修饰符都可以在这里看到。
5 H/ F' T2 |& H# X& y( h
编译智能合约
# e4 t4 r( c, b" [6 w
我们将会使用上一节安装的solc库来编译代码。如果你还记得的话,之前我们提到过web3js是一个库,它能够让你通过RPC与区块链进行交互。我们将会在node控制台里用这个库部署合约,并与区块链进行交互。; W( O" a7 y* r0 k" ?
, m- ?" \# u4 B2 u" B
首先,在终端中运行node进入node控制台,初始化web3对象,并向区块链查询获取所有的账户。
确保与此同时ganache已经在另一个窗口中运行# P3 B8 H, T9 G8 [" O
4 D5 x0 J' P, _1 B) Y/ Z
为了编译合约,先从Voting.sol中加载代码并绑定到一个string类型的变量,然后像下边这样对合约进行编译。/ r* ^3 _ X' y
$ I% }0 }: U& D' \
$node8 t x' b* C+ z5 ?5 F/ P4 V# }
) p2 Q3 D6 W" @! A
Inthenodeconsole
>Web3=require('web3'), l ]- r# D+ i9 o8 P7 d. x
>web3=newWeb3(newWeb3.providers.HttpProvider("http://localhost:8545"));
>web3.eth.accounts
* [) {/ U9 N4 s: l. l4 h3 x5 b3 c8 k
['0x5c252a0c0475f9711b56ab160a1999729eccce97'
'0x353d310bed379b2d1df3b727645e200997016ba3'7 E7 i+ G y) h) K O; `. C
'0xa3ddc09b5e49d654a43e161cae3f865261cabd23'
'0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5'
'0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798'
* [! d/ x1 p) m- n$ t
'0xda695959ff85f0581ca924e549567390a0034058'
3 G/ O7 K& k: R7 K4 S+ _3 H
'0xd4ee63452555a87048dcfe2a039208d113323790'8 p+ E: W3 a C- n" @4 |
) Y! p8 ~/ S8 p, E1 r
'0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14'- b" J' s8 j" ?4 D7 N9 D, V& J+ c2 s
'0xba7ec95286334e8634e89760fab8d2ec1226bf42'' Z' t& L8 A+ v+ y( j5 d7 K
' f1 G# L9 X1 k, [8 t; n
'0x208e02303fe29be3698732e92ca32b88d80a2d36']- O! ~1 o& a- G# [% l; Y
>code=fs.readFileSync('Voting.sol').toString()% G# ?+ M- B" U' M7 z
, ~" \& D: ^, h
>solc=require('solc')$ ]! `8 o, x9 @7 z' T/ R3 l1 z
>compiledCode=solc.compile(code)
当你成功地编译好合约,打印compiledCode对象(直接在node控制台输入compiledCode就可以看到内容),你会注意到有两个重要的字段,它们很重要,你必须要理解:0 y; A. Y0 V& l
' h" E% Z$ Q9 G, m& d$ q
1.compiledCode.contracts[’:Voting’].bytecode:这就是Voting.sol编译好后的字节码。也是要部署到区块链上的代码。
9 `; \( d' [3 z/ c
2.compiledCode.contracts[’:Voting’].interface:这是一个合约的接口或者说模板(叫做abi定义),它告诉了用户在这个合约里有哪些方法。在未来无论何时你想要跟任意一个合约进行交互,你都会需要这个abi定义。你可以在这里看到ABI的更多内容。
X3 @- n3 U0 P6 ^# W
教程参考汇智网的DAPP开发入门教程,如果大家等不及博客更新,也可以直接访问这个以太坊教程。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
成为第一个吐槽的人