如何通过solc编译solidity编写的以太坊智能合约
曲水流觞113
发表于 2022-11-6 23:42:53
174
0
0
solidity编写的以太坊智能合约可通过命令行编译工具solc来进行编译,成为以太坊虚拟机中的代码。solc编译后最终部署到链上形成我们所见到的各种智能合约。
" u5 K# A p' w. O( f$ p
作为一个solidity命令行编译工具,我们来看看官网都怎么说solc。
. D0 ~) N5 o: r/ q
solc的安装很简单:2 D4 a: ? j4 _2 V; I
npminstall-gsolc
7 r' }9 g( `4 M, {3 R: l
//或者, P$ d+ n* F' B+ X: `- d
4 I" b* J9 u6 S# T" R& v. i
npminstall-gsolc-cli
//或者
sudoapt-getinstallsolc+ U' N4 ?# E2 b8 I p( j1 L5 _6 {% @
安装完成后我们来看,solc--help,solc--help命令显示所有的solc命令选项。编译器可以生成各种输出,比如最终的二进制合约文件、语法树的汇编或者需要预计的要花费的gas等。solc--binsourceFile.sol,可以编译后输出一个名为sourceFile.sol的智能合约文件。如果你想从solc获得更丰富的一些输出变量,你可以使用solc-ooutputDirectory--bin--ast--asmsourceFile.sol。8 [1 [1 R$ [, ^( n
1 ^. e( @2 D% |! K2 s5 t1 d, Q
你在部署以太坊智能合约之前可以用solc--optimize--binsourceFile.sol优化一下。默认情况下solc编译器会帮你优化200次。你也可以设置--runs=1,这样就按照最小化的方式进行编译,如果你希望多次交易不太在乎成本,那你可以设置成你想要的次数:)。
命令行编译器会自动读取需要导入的文件,也可以通过使用prefix=path来指定路径,例如:
solcgithub.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/=/usr/local/lib/fallbackfile.sol' ^- ?+ ~2 y; J( e, x
' V z! Q: [- b3 t; ^
这样编译器就会从指定目录github.com/ethereum/dapp-bin/下的/usr/local/lib/dapp-bin/目录开始搜索,如果没有找到文件,它将查看/usr/local/lib/fallback。solc将只读取你指定的这两个路径的,因此像import"/etc/passwd";必须要通过/=重新映射才起作用。如果有多个匹配,则选择具有最长公共前缀的进行匹配。
: G, f) w8 x! s) W3 [% V
出于安全上的考虑,编译器限制了它可以访问的一些目录。在命令行中指定的源文件的路径(及其子目录)和命令行指定的路径外其他所有内容都会被拒绝。--allow-paths/sample/path,/another/sample/path来切换。% |$ L8 Q. Q% T- [
4 Q* t9 L2 C- w8 @3 N9 b6 E; U
如果智能合约使用了libraries,你会注意到字节码包含了__LibraryName______的子字符串。您可以使用solc作为链接器,这意味着它将在这些点为您插入库地址。: E7 O* n) H" ^( L6 L
) U3 {4 B8 i4 C' L3 C# k
可以通过添加库--libraries"Math:0x12345678901234567890Heap:0xabcdef0123456"到您的命令,以提供每个库的地址,或者使用文件中的说明字符串(每行一个库),并使用--librariesfileName运行solc。8 |& N3 u, e! g8 \. h2 ]
如果用选项--link调用Solc,则所有输入文件都被解释为未链接的二进制文件(HEX编码),在上面给出的__LibraryName____格式中,将其链接到适当地址(如果从stdin读取输入,则将其写入stdout)。在这种情况下,除了库外,所有选项都被忽略(包括-o)。, }7 B& A2 X5 ]1 m' I
如果用--standard-json调用SOLC,它就将标准的JSON输入(如下所述),并返回JSON输出。
& n5 M6 l N; `1 x6 L7 {
#solc编译器输入输出JSON描述* F" d, J- B0 p- G7 W0 h8 p5 e
, R# \( ^& Q3 \8 ?
这些JSON格式通过编译器API使用,可以通过SOLC获得。内容都是可以修改的,一些对象是可选的(如前所述),其目的是向后兼容。
* Y( F! {8 [1 C: ?$ p; g) p
编译器的API需要一个JSON格式的输入,然后以JSON格式输出编译结果。4 _) |* F& X0 k+ g4 t
注意不允许注释。下面示例中的注释,是官网为了学习者更好的理解标注的。
输入格式说明:, x9 b0 w6 x* R. y* C0 D; P N
{9 |4 _5 \9 c, [
9 O8 _. G2 ]5 r/ a
//Required:Sourcecodelanguage,suchas"Solidity","serpent","lll","assembly",etc.
language:"Solidity",# L9 D- e4 F/ c
3 K# ?4 E! g; s, C. g. t
//Required$ ~0 B8 [4 ~8 ^" H5 B$ R; b
1 w% t& Y y! f, \8 z9 q1 G
sources:
* C j$ u/ g2 f/ A7 A3 E
{
6 m; e; ]3 Q) J+ a# k* g
//Thekeysherearethe"global"namesofthesourcefiles,4 @- b3 t! Y; x
//importscanuseotherfilesviaremappings(seebelow).
"myFile.sol":0 Q( A" Z% m$ x1 d0 z6 V% l2 [# S
{
//Optional:keccak256hashofthesourcefile
//ItisusedtoverifytheretrievedcontentifimportedviaURLs.
"keccak256":"0x123...",
//Required(unless"content"isused,seebelow):URL(s)tothesourcefile.
. E7 j8 C! E v; t! L0 V
//URL(s)shouldbeimportedinthisorderandtheresultcheckedagainstthe% {: ?- W6 Z( a* f' j1 N9 Z
//keccak256hash(ifavailable).Ifthehashdoesn'tmatchornoneofthe
//URL(s)resultinsuccess,anerrorshouldberaised.
"urls":5 _2 @0 |. O$ R; k9 L8 {# K
/ j+ w8 b0 P8 m" t4 c! H9 C3 R
[% Z: z$ \6 t5 ^
8 j: C. P" w* |
"bzzr://56ab...",% d! r' W. F% O8 ?6 m
1 I. P1 i& o, T: F; G
"ipfs://Qma...",$ U& ?) q- \5 v v- u
"file:///tmp/path/to/file.sol"+ F4 Y4 }- c! q/ m" e6 S
0 Y5 |8 f. p7 Y; o# M
]) a9 i7 N3 U" t0 I- L `
},0 L' U9 M) d5 n% f
# U0 W9 }8 `7 n( X8 q9 h& F
"mortal":
$ p) b. z; N2 O
{
8 K' e4 R7 C# D1 G0 I% S I
//Optional:keccak256hashofthesourcefile8 E6 o& r9 ^, M2 m
"keccak256":"0x234...",
* G9 q4 _+ d6 |0 J' ?6 w
//Required(unless"urls"isused):literalcontentsofthesourcefile
"content":"contractmortalisowned{functionkill(){if(msg.sender==owner)selfdestruct(owner);}}"
}: p% |5 A- P" C Z9 e8 Y
$ X2 N& z( _! f) K8 c7 t# W
},2 O( ~$ Q; H' N1 ? R
, k2 J( S v) j. D8 m
//Optional
settings:+ n. V9 x1 b& L4 Y
/ b7 @( [2 S! z% w4 K7 z8 {8 R. {
{
//Optional:Sortedlistofremappings
remappings:[":g/dir"],& B2 S/ m) m [5 a2 f
3 t; c$ l7 |% k
//Optional:Optimizersettings
optimizer:{
; u' I' y7 U! P1 \" R) w4 @. d
//disabledbydefault
! v1 B3 c% N1 [/ f, n# c
enabled:true,
- W, o; |$ x/ n8 o6 @
//Optimizeforhowmanytimesyouintendtorunthecode.4 x O3 l) Q7 x4 A+ ]
//Lowervalueswilloptimizemoreforinitialdeploymentcost,highervalueswilloptimizemoreforhigh-frequencyusage.4 A D! |5 r" l6 C
runs:200
},
evmVersion:"byzantium",//VersionoftheEVMtocompilefor.Affectstypecheckingandcodegeneration.Canbehomestead,tangerineWhistle,spuriousDragon,byzantiumorconstantinople
//Metadatasettings(optional)
' v7 \5 }9 n# r+ b% f
metadata:{
//UseonlyliteralcontentandnotURLs(falsebydefault)
3 @+ B# w6 Z+ G f& s l9 \
useLiteralContent:true! i6 w& ~4 j8 X+ z" ^1 g5 v
1 B9 M0 S8 O3 d4 L
},' i& W% t0 k* n/ `: J; e% a' u- w
//Addressesofthelibraries.Ifnotalllibrariesaregivenhere,itcanresultinunlinkedobjectswhoseoutputdataisdifferent.1 g1 D# d) G* |: [
0 K: }% P% n+ l, @2 Z
libraries:{
//Thetoplevelkeyisthethenameofthesourcefilewherethelibraryisused.
//Ifremappingsareused,thissourcefileshouldmatchtheglobalpathafterremappingswereapplied., f: z- [: c4 P" A8 {
//Ifthiskeyisanemptystring,thatreferstoagloballevel.
( q: a1 X0 B' u1 r/ w$ `
"myFile.sol":{
9 c6 `& t- k _$ D+ [5 w1 |) ]! [
"MyLib":"0x123123..."
( X6 e# A+ C2 t; w, `
}% S0 K6 a1 W( P+ v. U4 |+ c. l$ e5 c
}
, `5 b' h: U w1 S( n: z
//Thefollowingcanbeusedtoselectdesiredoutputs.3 \3 N# k: h, D' L4 R
//Ifthisfieldisomitted,thenthecompilerloadsanddoestypechecking,butwillnotgenerateanyoutputsapartfromerrors.. k" ?5 N0 H7 j( [* j c- k
//Thefirstlevelkeyisthefilenameandthesecondisthecontractname,whereemptycontractnamereferstothefileitself,
//whilethestarreferstoallofthecontracts.
//' Z2 J* b2 _# B; ]3 G* {9 |5 ^3 Y) Q
//Theavailableoutputtypesareasfollows:
. G) @/ V4 C- f" l; c
//abi-ABI
//ast-ASTofallsourcefiles1 l8 S" i! c, Y: F( s( R' D
//legacyAST-legacyASTofallsourcefiles
//devdoc-Developerdocumentation(natspec)( j! X j8 ]7 Y) B+ @4 u/ ?
//userdoc-Userdocumentation(natspec)
8 Q9 {8 N/ [0 @+ l
//metadata-Metadata6 V5 K& |# g4 W# y' @5 R* l6 `
( g, C# L- D5 i0 U. g% F% y+ z; ~' j
//ir-Newassemblyformatbeforedesugaring
/ \3 o3 P/ Y: }0 t/ u0 d9 S1 m( o
//evm.assembly-Newassemblyformatafterdesugaring3 W7 J" K- S( a& N1 u
//evm.legacyAssembly-Old-styleassemblyformatinJSON
/ u; u: t: `- c+ f: ` R
//evm.bytecode.object-Bytecodeobject
, W$ @2 m* l; G1 v X
//evm.bytecode.opcodes-Opcodeslist/ y. ~( A6 j( L! x }5 w( A
! K5 ]( l Y+ }- G
//evm.bytecode.sourceMap-Sourcemapping(usefulfordebugging)
//evm.bytecode.linkReferences-Linkreferences(ifunlinkedobject)
9 s+ M0 |- y' t S- |
//evm.deployedBytecode*-Deployedbytecode(hasthesameoptionsasevm.bytecode)7 l+ I: Z8 j+ b \& c. [# J5 G
5 H$ M, W& I1 l5 E6 A8 H. m
//evm.methodIdentifiers-Thelistoffunctionhashes
: @5 m+ _% z$ D! _6 a4 d! n
//evm.gasEstimates-Functiongasestimates% H0 s. C' A; B9 L8 w4 e: m' {
//ewasm.wast-eWASMS-expressionsformat(notsupportedatm)
//ewasm.wasm-eWASMbinaryformat(notsupportedatm)5 E1 }5 |$ D6 v: I+ s
5 N+ h' o* @0 q4 p4 n
//
//Notethatusingausing`evm`,`evm.bytecode`,`ewasm`,etc.willselectevery, d9 ?! p+ w+ O0 V. I
//targetpartofthatoutput.Additionally,`*`canbeusedasawildcardtorequesteverything.
$ n4 ^6 ]. @$ J) @( I- s+ J* X2 ^. {
//6 T; G* `) s2 \- {
outputSelection:{
//Enablethemetadataandbytecodeoutputsofeverysinglecontract.
"*":{8 Z! ^* ^' Z4 h& q. C- l
- U- W7 q V4 l
"*":["metadata","evm.bytecode"]8 E v1 P! I! \5 S+ ~. d
5 ?2 O* O! [, j8 [
},
//EnabletheabiandopcodesoutputofMyContractdefinedinfiledef.* i0 j2 ^$ P; O
"def":{ x7 u( j& w0 z
"MyContract":["abi","evm.bytecode.opcodes"]
4 l3 j! u: M0 _( n5 _& r7 w
},+ j& {9 A$ ?2 Y1 v* w( j4 U$ e
& {& S+ J B) C
//Enablethesourcemapoutputofeverysinglecontract. Q T; T' ~* ~6 n! p/ [
"*":{
"*":["evm.bytecode.sourceMap"]3 g ^$ ? A* P( \" c2 j M- [
7 e8 u0 W6 z( U( H! x
},
//EnablethelegacyASToutputofeverysinglefile.; J2 ]" Y" W9 r
: z: t- _' o% d
"*":{! a3 Z0 `7 i/ e$ u4 d l+ s
"":["legacyAST"]
9 k: O) j$ |. w L7 I7 }+ K6 b
}0 W, V% f9 q0 e+ [ X2 _# l3 }
}1 ~/ y& x) [* b
4 Y @- \- Q* Z4 S0 ~
}$ N; A! y# S4 ~8 v& }
}
% d/ c3 |; p5 z G
输出格式说明
{1 M) W4 |+ {" J* \ m6 f
- R2 T5 }, I5 `. e8 u, e3 ?
//Optional:notpresentifnoerrors/warningswereencountered
, ~9 R" L" X- W6 X
errors:[
{$ c+ h. n3 x$ B4 J8 ]
# c# {0 S) U$ K! k
//Optional:Locationwithinthesourcefile.
sourceLocation:{
file:"sourceFile.sol",
start:0,
end:100
. o. B/ v) H% j8 g+ \' Q: w0 b6 y2 M
],
//Mandatory:Errortype,suchas"TypeError","InternalCompilerError","Exception",etc.
//Seebelowforcompletelistoftypes./ T6 {' d4 Q6 Q" p
* r L4 ^& @+ }1 k( S# T9 j
type:"TypeError",
0 T, ~* X0 x' w9 m( E! m
//Mandatory:Componentwheretheerrororiginated,suchas"general","ewasm",etc.) C0 G* Z! P' J B3 k
( z j( v3 K7 j" F& A, R! `5 s- d
component:"general",4 T5 O( K/ o% `; e8 N- A0 T: x$ @
3 Y5 F( J u4 n
//Mandatory("error"or"warning")
- i* J: K% D& G& U9 \6 w% l: p3 d p
severity:"error",
8 d3 Y& N4 F+ c" v- @+ J i
//Mandatory
! \6 @5 o$ N' Q- I9 `0 Y- h; b
message:"Invalidkeyword"
//Optional:themessageformattedwithsourcelocation
formattedMessage:"sourceFile.sol:100:Invalidkeyword". m0 W% u% ?1 ^8 @4 m: O
7 N, c F# q0 M3 H# T" d" _: v
}! o+ B5 U z0 F% a! `2 g! }2 a' C
],
* _/ ~# Q! ~& J5 X% u
//Thiscontainsthefile-leveloutputs.Incanbelimited/filteredbytheoutputSelectionsettings.' `9 \$ D; F% d+ m- @
4 L0 L1 M7 b) V( d k2 k7 Q
sources:{
0 V$ l- O! j8 Q- c6 Y
"sourceFile.sol":{
/ s$ ^4 D' g: w: d/ m8 w; G
//Identifier(usedinsourcemaps)" f* N. ?, J9 f* S
- V M% }! N4 W: I2 U; a2 u
id:1,' E1 E5 |$ a6 t& l& y% G
//TheASTobject j* f) x# P( j
ast:{},
//ThelegacyASTobject1 d' M {4 t. x; W3 s
) V) c3 q# a! G7 J
legacyAST:{}
}
3 s8 C! Z) m0 P) d C! `$ b( q
},1 U1 f# `2 M' T9 c) [0 c
+ \# C1 H; B; F% I. R9 w4 }8 y; Q
//Thiscontainsthecontract-leveloutputs.Itcanbelimited/filteredbytheoutputSelectionsettings.+ z: s: I* D, }/ B
contracts:{2 r4 J, w5 Y8 j3 R! y
"sourceFile.sol":{( k9 D, W. M6 D- ^' D
( ?. [- n7 S3 T$ l1 E2 I
//Ifthelanguageusedhasnocontractnames,thisfieldshouldequaltoanemptystring., ^/ I4 M" m, i: H$ |9 A8 d# J
"ContractName":{
//TheEthereumContractABI.Ifempty,itisrepresentedasanemptyarray.! r; o% s/ W4 ~4 A9 U' k2 x4 _& Q) o
//Seehttps://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI: l" o: K0 o* h4 z/ w8 G
abi:[],
//SeetheMetadataOutputdocumentation(serialisedJSONstring)
metadata:"{...}",* C) X: q x" Y
0 [4 h# ^. E/ u: ^( f/ Z/ t- a' c
//Userdocumentation(natspec)
1 ~4 _6 ^; |8 r; F2 K# g5 J9 v
userdoc:{},5 S. s, `0 c8 y% G# H/ n
//Developerdocumentation(natspec); X6 b- w, c, {
0 T1 `: k" N+ z/ b7 p' S% g, J5 Y% j
devdoc:{},
//Intermediaterepresentation(string)! S* b3 u& J O& m5 B( q
0 Q. w: V1 A4 N0 u, J* G6 @/ c7 p
ir:"",
//EVM-relatedoutputs4 Z* I5 v; b w
: C: L* x; W' O" U
evm:{
( j, i4 ]! c8 v& E
//Assembly(string)
assembly:"", p& \+ w# L( T, Q. G! x
/ P$ u; G* p/ m$ }$ v
//Old-styleassembly(object)
legacyAssembly:{},
3 F' _+ r! p7 q- `6 F4 W( u- H
//Bytecodeandrelateddetails.: `2 s# b+ `6 Z L' ^
bytecode:{4 S; g V* @/ Z5 b @/ g/ K: t
7 p- W( q- |( T7 @% I. Y
//Thebytecodeasahexstring.! K) v& C% Z. Y1 N" _
object:"00fe",9 G$ n1 X5 e9 ?% R
//Opcodeslist(string)) r/ v! Y' S0 r' ]4 P. Q3 z
opcodes:"",+ T, ?& {" y6 O) d- l- {
//Thesourcemappingasastring.Seethesourcemappingdefinition.
9 ?% q; }4 }- |0 Y( k
sourceMap:"",
, t# t9 q' H4 [
//Ifgiven,thisisanunlinkedobject.1 r: W2 \* \5 z9 @5 l/ O
linkReferences:{
"libraryFile.sol":{
//Byteoffsetsintothebytecode.Linkingreplacesthe20byteslocatedthere.7 o/ u' _ T1 N5 W+ {5 s' ~
"Library1":[1 v8 p2 Q1 f1 n- ~. i
{start:0,length:20},
2 Q P m3 V2 Q( ^& T
{start:200,length:20}: q4 ]! N, X& v2 S
]
0 G% B# w& e ~# z: w
}
}
},
3 @- ?- E: ]3 {, J$ W
//Thesamelayoutasabove.* K& o& _/ @) R. r% E- ]
( z6 Z/ h% B1 o( _9 u4 I
deployedBytecode:{},
3 O: i& Y3 J+ t2 Q0 l* E4 [ H
//Thelistoffunctionhashes( P: R; ~# R3 q% q9 j) {0 G2 @: P
methodIdentifiers:{
"delegate(address)":"5c19a95c"
},
# r0 s( w& ^8 L: x/ A
//Functiongasestimates
gasEstimates:{( a3 ^" h! ?( j/ \. A
; K* J$ b5 l+ R0 E: r0 F4 { P
creation:{
9 u3 v& J% ], V' E
codeDepositCost:"420000",
executionCost:"infinite",
" d6 W) {. f( \6 t! \0 i
totalCost:"infinite"" D& _8 Y# K( d% U2 V
},& Z, B: @' s) V" n# N
# _* z/ J, `: c
external:{
" p) M6 G; k; [' p0 V# V" D2 m3 F
"delegate(address)":"25000"; b! I2 K4 H% k. H/ m! ]+ ?
0 B* x/ T$ H& `8 G1 m- b v( [
},8 h$ P$ x* |* U/ B
+ N5 S) N7 x# F Q1 ?
internal:{
8 J: Q0 L2 y% _, j+ R
"heavyLifting()":"infinite"+ {- m" w7 a4 s) J/ Q: G
/ [8 i0 {. w" d
}
}+ f9 m! S8 a$ S- C) q* r7 u# b3 K2 G
},! n& M: u. S- N) u2 O, v$ b9 S
//eWASMrelatedoutputs. I; A5 G' ]$ L2 f# Q5 T$ z
ewasm:{
//S-expressionsformat
5 N$ K8 w: @% C" k
wast:"",
. _ R& v6 e9 l
//Binaryformat(hexstring)
wasm:""9 ]9 |7 O: x7 |6 j8 K5 |
}
7 E/ u& t8 e$ F- P# W2 q v( t5 d" Y2 R
}- m6 k! ]8 G2 C7 y0 B
% ^2 g# | L* [( F
}
7 [1 A7 |! E% c$ C
}8 B) H0 S. Q: E! G K; h
}
错误类型说明:$ i# x6 q) H+ k% H. l) V
6 u+ {9 n! C3 I3 f4 r
1 y. p) R, r, N$ ^+ a. W' z
1 ^4 ], e/ v; u6 ]" e" l/ g
JSONError:JSON错误,JSON输入不符合要求的格式,例如输入不是JSON对象,不支持语言,等等。# z+ |; E' X" D$ ^5 y
IOError:IO错误,IO和导入处理错误,如提供的源中的不可解析URL或hash不匹配。
ParserError:语法f分析错误,源代码不符合语言规则。
* t8 q( G6 l. E3 P2 b. J. R7 s
DocstringParsingError:文档解析错误,无法解析注释块中的NATSPEC标记。
1 T5 R6 E0 ]5 @: g& i @4 @
SytRealError:语法错误,如continue在for循环之外使用。
4 ~/ J0 v, [' V% ~2 U7 R/ A) N
DeclarationError:声明错误,无效、不可解析或冲突的标识符名称。例如未找到标识符
1 y: o3 `; J# a
TypeError:类型错误,如无效类型转换、无效赋值等。
. B R) B1 s+ q8 X9 M0 o4 V) x
UnimplementedFeatureError:编译器不支持该特性,但希望在将来的版本中得到支持。
9 p# t6 K# |. O1 |3 F6 O2 E4 {; k- a
InternalCompilerError:编译器中触发内部错误,这应该作为一个问题来反馈。 \5 l3 x: E" ?) H
Exception:例外,编译过程中未知的故障,这应该作为一个问题反馈。% e* J& g1 X: Q, ^# a0 w1 l
CompilerError:编译错误,编译器堆栈的使用无效,这应该作为一个问题来反馈。; y8 l4 h; y; Y; b1 t* g
FatalError:致命错误,这应该作为一个问题来反馈。8 S; N. V c/ R
& |" E/ F, b% E( Z" h2 f
Warning:警告并没有停止编译,但如果可能的话,应该加以处理。
2 c! d; x5 J! L! i$ [5 Q/ Y0 H
: x( h1 T- I# [; _% _
原文请访问:solc2 O/ f/ j, N5 w/ W. ?! ]' S+ ]/ t
+ G( t# L. Z7 Q2 s7 |
如果你希望马上开始学习以太坊DApp开发,推荐访问一个在线教程:
以太坊智能合约,主要介绍智能合约与dapp应用开发,适合入门。
) t1 R: V, h' f# n: a
以太坊开发,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
成为第一个吐槽的人