如何通过solc编译solidity编写的以太坊智能合约
曲水流觞113
发表于 2022-11-6 23:42:53
121
0
0
solidity编写的以太坊智能合约可通过命令行编译工具solc来进行编译,成为以太坊虚拟机中的代码。solc编译后最终部署到链上形成我们所见到的各种智能合约。
D |! R# \' E U, f' o
作为一个solidity命令行编译工具,我们来看看官网都怎么说solc。* P. u5 T2 q, t- \) Q
* y' a% K1 k% B+ U
solc的安装很简单:0 v! E% x6 i3 t$ ^; Q
$ C e, G* w# i+ }5 _" }) {
npminstall-gsolc
. _. {) n7 E1 j) D3 {
//或者7 [, }5 ?$ T( I
! g9 t6 _6 f3 w: K' ?
npminstall-gsolc-cli# v% O, q6 ]6 M' @; }& S
//或者7 D9 I! s5 U9 g6 c9 a
4 f0 i' H J& U: W
sudoapt-getinstallsolc; O6 L- X! [) g# e& z- S
安装完成后我们来看,solc--help,solc--help命令显示所有的solc命令选项。编译器可以生成各种输出,比如最终的二进制合约文件、语法树的汇编或者需要预计的要花费的gas等。solc--binsourceFile.sol,可以编译后输出一个名为sourceFile.sol的智能合约文件。如果你想从solc获得更丰富的一些输出变量,你可以使用solc-ooutputDirectory--bin--ast--asmsourceFile.sol。 K# N4 L/ |# T; J
你在部署以太坊智能合约之前可以用solc--optimize--binsourceFile.sol优化一下。默认情况下solc编译器会帮你优化200次。你也可以设置--runs=1,这样就按照最小化的方式进行编译,如果你希望多次交易不太在乎成本,那你可以设置成你想要的次数:)。
' a9 e8 g1 r$ S. q: }# c% Y1 x/ l
命令行编译器会自动读取需要导入的文件,也可以通过使用prefix=path来指定路径,例如:& z: n- c0 @" S* p7 O9 o
solcgithub.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/=/usr/local/lib/fallbackfile.sol
这样编译器就会从指定目录github.com/ethereum/dapp-bin/下的/usr/local/lib/dapp-bin/目录开始搜索,如果没有找到文件,它将查看/usr/local/lib/fallback。solc将只读取你指定的这两个路径的,因此像import"/etc/passwd";必须要通过/=重新映射才起作用。如果有多个匹配,则选择具有最长公共前缀的进行匹配。0 Z* L( [% |+ t( L/ B
; b- q- s+ r/ j2 [* H' g7 S; l
出于安全上的考虑,编译器限制了它可以访问的一些目录。在命令行中指定的源文件的路径(及其子目录)和命令行指定的路径外其他所有内容都会被拒绝。--allow-paths/sample/path,/another/sample/path来切换。+ V2 e) n/ t7 C; o' `
如果智能合约使用了libraries,你会注意到字节码包含了__LibraryName______的子字符串。您可以使用solc作为链接器,这意味着它将在这些点为您插入库地址。7 Z) L. h2 W; t- G. Q, l
可以通过添加库--libraries"Math:0x12345678901234567890Heap:0xabcdef0123456"到您的命令,以提供每个库的地址,或者使用文件中的说明字符串(每行一个库),并使用--librariesfileName运行solc。7 t( q( m9 i: u- K8 _) o0 B1 G
- m; a6 t' ?: u- q8 I6 r
如果用选项--link调用Solc,则所有输入文件都被解释为未链接的二进制文件(HEX编码),在上面给出的__LibraryName____格式中,将其链接到适当地址(如果从stdin读取输入,则将其写入stdout)。在这种情况下,除了库外,所有选项都被忽略(包括-o)。/ f# _/ U/ W1 h9 W& O I
如果用--standard-json调用SOLC,它就将标准的JSON输入(如下所述),并返回JSON输出。
#solc编译器输入输出JSON描述2 ?( |2 f7 J7 M. g2 q# [' T" E& I
这些JSON格式通过编译器API使用,可以通过SOLC获得。内容都是可以修改的,一些对象是可选的(如前所述),其目的是向后兼容。
编译器的API需要一个JSON格式的输入,然后以JSON格式输出编译结果。 s1 A. O0 J7 G; J% M2 n: a3 t2 [$ M
. g5 \. A$ H' i! Z- r
注意不允许注释。下面示例中的注释,是官网为了学习者更好的理解标注的。
- R1 I$ t4 `' M, Q& g4 I. O# @
输入格式说明:
$ J+ w5 D" G2 U3 R2 @1 c
{
5 ?9 l/ S+ e* g6 s# H6 A9 \
//Required:Sourcecodelanguage,suchas"Solidity","serpent","lll","assembly",etc.
$ B; R* L6 S2 H
language:"Solidity",
3 z- r5 E/ z, @
//Required! U$ a5 U+ E( }1 O+ D' d: _
5 ~- ]: b1 @0 H0 u$ A
sources:) l3 C* M" K' f7 [4 g( ]
- n v! N* l3 E: H. m5 ^8 P9 S' W
{, F6 L" o! s) f E. p3 {
2 W* M8 c9 p$ d8 V
//Thekeysherearethe"global"namesofthesourcefiles,
//importscanuseotherfilesviaremappings(seebelow).! B$ ^$ R# _8 z- b# @
"myFile.sol":2 Q8 P$ Y: f1 Q" g. `0 Y
: I; H n+ F9 t# v" p# u; `
{
8 }, e! i0 ]3 s2 E
//Optional:keccak256hashofthesourcefile
//ItisusedtoverifytheretrievedcontentifimportedviaURLs.7 g% [& N8 T& i- i( T, \
"keccak256":"0x123...",; R& A, e C9 |8 N& `& `4 H
" F2 k% N3 a; O% t( s
//Required(unless"content"isused,seebelow):URL(s)tothesourcefile.6 v1 ^ z+ j- ` c3 v
//URL(s)shouldbeimportedinthisorderandtheresultcheckedagainstthe9 M; @' |! D! W$ S' _. n& Z& V
//keccak256hash(ifavailable).Ifthehashdoesn'tmatchornoneofthe3 w. e; D8 r# R
" ~" Y7 w* U% X% t- P
//URL(s)resultinsuccess,anerrorshouldberaised.* ^. o4 @( e9 C( E
"urls":# }/ j/ f7 r$ y$ H
[! ?% k' _- V% a. A
/ j7 d; z* t( g$ b0 V
"bzzr://56ab...",9 k/ h# f" t% \3 K8 c" U6 a' F
"ipfs://Qma...",, C! H+ t* @0 Y* j% c' u
"file:///tmp/path/to/file.sol"
]& l# U* U; C# m: X
- n2 O6 n8 f, w) V$ Q: y
},
, t0 y8 o% Y7 J" u8 x
"mortal":
{
//Optional:keccak256hashofthesourcefile* r7 f7 C: Y( g
"keccak256":"0x234...",
//Required(unless"urls"isused):literalcontentsofthesourcefile
"content":"contractmortalisowned{functionkill(){if(msg.sender==owner)selfdestruct(owner);}}"
}, @# m* y4 H4 x0 G- x
# R ]; Y. q) W, E) k
},
- J! F5 Z4 X, S% q) p o% K2 M
//Optional
settings:
{
) L5 s# K: V4 w6 ~6 ]/ ~
//Optional:Sortedlistofremappings% D0 u5 m5 B# Y$ x
/ ^3 @ G( l- x: H2 T6 [4 U1 X
remappings:[":g/dir"],
//Optional:Optimizersettings ~2 S" y) v& f& b3 \$ e. b4 P/ e
optimizer:{
# f& ]* A4 K ]- ^4 ^" C3 U
//disabledbydefault
enabled:true,# i1 k0 Q7 { z& _6 C! J
, p% y7 r- w; [2 O2 b: I
//Optimizeforhowmanytimesyouintendtorunthecode.
//Lowervalueswilloptimizemoreforinitialdeploymentcost,highervalueswilloptimizemoreforhigh-frequencyusage.
, S" F2 k }% G! v) d" \4 ^
runs:2008 {. A! A* R# Q7 F6 J j
},
evmVersion:"byzantium",//VersionoftheEVMtocompilefor.Affectstypecheckingandcodegeneration.Canbehomestead,tangerineWhistle,spuriousDragon,byzantiumorconstantinople
//Metadatasettings(optional)4 a" t+ W- s3 U! N9 n
+ U! x! P! A* } |1 a
metadata:{
5 y4 L6 q5 g- q$ i- g* Z6 N
//UseonlyliteralcontentandnotURLs(falsebydefault)* A1 e! X U- J1 P
useLiteralContent:true
},
) h8 W/ k2 f# n1 ^4 F/ l4 V
//Addressesofthelibraries.Ifnotalllibrariesaregivenhere,itcanresultinunlinkedobjectswhoseoutputdataisdifferent.
libraries:{# |. u1 {0 Z7 d$ n9 i
//Thetoplevelkeyisthethenameofthesourcefilewherethelibraryisused.
//Ifremappingsareused,thissourcefileshouldmatchtheglobalpathafterremappingswereapplied.
//Ifthiskeyisanemptystring,thatreferstoagloballevel.
"myFile.sol":{8 T3 p+ ~7 e& i0 K
! ^1 W6 o5 e5 @) i5 s
"MyLib":"0x123123..."/ l. L. Z# D& c. z6 c
}
( S! `( O7 z$ `
}! E- w- h- g* c
& c7 ]0 s1 q8 {! B2 K
//Thefollowingcanbeusedtoselectdesiredoutputs.
! e+ z+ y& o9 [" R* O% E
//Ifthisfieldisomitted,thenthecompilerloadsanddoestypechecking,butwillnotgenerateanyoutputsapartfromerrors.6 e; o7 B" H4 q: d7 o- b
6 x2 a+ A* H; U. F% x: b
//Thefirstlevelkeyisthefilenameandthesecondisthecontractname,whereemptycontractnamereferstothefileitself,# K4 Q! x4 c! a0 E
& Q6 i& S2 N( @3 }9 V* T* L& ~
//whilethestarreferstoallofthecontracts.) |) A( _ L5 c6 I$ ^; w$ R. [6 D
5 T' w6 U: \8 D# Y% C+ ]
//
# u5 L0 L& G- w F& x
//Theavailableoutputtypesareasfollows:* }) `4 B% s# X1 S0 t
//abi-ABI
//ast-ASTofallsourcefiles
//legacyAST-legacyASTofallsourcefiles
//devdoc-Developerdocumentation(natspec)' k" [4 }/ l! i# C' g
5 ^' r1 S/ c+ ~
//userdoc-Userdocumentation(natspec)* t9 `- D# A: S1 Z, r2 W! d; p% H
//metadata-Metadata
/ h) r6 G% E+ n6 |' u! @; W
//ir-Newassemblyformatbeforedesugaring B1 ~/ s& i6 s1 G/ `* t
' v3 x; l$ Y h5 a+ m* i
//evm.assembly-Newassemblyformatafterdesugaring
//evm.legacyAssembly-Old-styleassemblyformatinJSON3 g7 y. j- ?2 _+ O. ^; f
//evm.bytecode.object-Bytecodeobject' o6 z8 b [, }
+ t8 o5 k; E7 d3 a! m
//evm.bytecode.opcodes-Opcodeslist+ T2 k4 ]; o/ P1 j! q
//evm.bytecode.sourceMap-Sourcemapping(usefulfordebugging)- t, M f/ M# C7 R r# L |
+ q. M; d* {# M9 o& S
//evm.bytecode.linkReferences-Linkreferences(ifunlinkedobject)
//evm.deployedBytecode*-Deployedbytecode(hasthesameoptionsasevm.bytecode)+ v2 }% B) G7 D4 x; |
* A; p+ S: Y7 w3 Y
//evm.methodIdentifiers-Thelistoffunctionhashes- Q# A5 N( [- u8 J4 T2 G
//evm.gasEstimates-Functiongasestimates
//ewasm.wast-eWASMS-expressionsformat(notsupportedatm)
7 a6 X; h0 E. x' m( T5 H
//ewasm.wasm-eWASMbinaryformat(notsupportedatm)9 T2 U( C% a* _+ f
8 y6 {9 t* J( C& Y S" C
//
2 w% T o3 D$ {+ [8 F! _
//Notethatusingausing`evm`,`evm.bytecode`,`ewasm`,etc.willselectevery
//targetpartofthatoutput.Additionally,`*`canbeusedasawildcardtorequesteverything. W& D$ i4 c# d5 b L9 @! S
K- q( O3 j. D7 H
//
% S5 n4 v4 F; d# t/ S
outputSelection:{
; p( X; a2 ^# k- x9 r% B
//Enablethemetadataandbytecodeoutputsofeverysinglecontract.0 s1 V5 m' U# U* w+ `( z. p
"*":{
2 Y/ N- r$ n. s1 h0 n) m
"*":["metadata","evm.bytecode"]
: P; D; C B- [
},
//EnabletheabiandopcodesoutputofMyContractdefinedinfiledef.3 w% R, a3 N0 M6 @/ w: `! s
"def":{+ C7 j6 a$ S1 N3 H+ c" S
: m) F# Q/ J- u1 b) s q
"MyContract":["abi","evm.bytecode.opcodes"]8 l) Z G0 G8 u
},+ ~! Q0 I ]) p/ ~- u' w' O; B
//Enablethesourcemapoutputofeverysinglecontract.
"*":{
1 u6 S; [" L, C+ A* Y$ o
"*":["evm.bytecode.sourceMap"]3 C' _* S3 l% R) |
' X& Y- N9 i6 D' Q& o
}, w9 H6 t3 H. H3 l
, r$ d: `. S# J* E0 _
//EnablethelegacyASToutputofeverysinglefile.
1 S8 ~/ Z+ d- P* \) j1 `
"*":{
4 H1 e+ X% D, x: h* Y6 [. @
"":["legacyAST"] r$ s/ a! t6 L$ H
}
4 G7 Z. p5 z+ O' V; y0 Y+ h. T
} @( v. _7 `1 E5 ^1 g# F8 j+ @5 L' p
}* K8 N. i* n; G& j/ n
}# ~0 t) v! b: X0 i% f3 P" O9 R
2 \. w8 A7 ~6 [ W8 d6 P
输出格式说明
4 k% [1 i) e! r- ?& S
{
//Optional:notpresentifnoerrors/warningswereencountered$ ?' f; l4 e. A! f
errors:[
{
q! G9 x$ g# j3 K6 O/ Q# W, {
//Optional:Locationwithinthesourcefile.
sourceLocation:{1 {$ d/ k' x' b+ Q J- Q# K
3 u" }; l# e) b* n- O3 ?
file:"sourceFile.sol",
# k8 V! z. Z0 R5 N: W- D
start:0,7 H% G: X. c; R/ _! y( W
9 L: T0 h! ]5 v( d F
end:100% v. t1 o. R2 u8 T
],
//Mandatory:Errortype,suchas"TypeError","InternalCompilerError","Exception",etc.
//Seebelowforcompletelistoftypes.! N* b! O0 Q. ?: C7 b/ F" N( m- |
$ K! `/ [% t) @+ d& D, o+ n
type:"TypeError",6 D* Y0 }( ]2 N" Y# b8 Q
0 L, u! _4 c( i! G4 F+ f
//Mandatory:Componentwheretheerrororiginated,suchas"general","ewasm",etc.2 O0 r: u$ J- [4 K; `) g7 Y/ L
component:"general",$ \" d& d! H( Q) `( G- d: ?
+ N" v1 L B: R) c ^
//Mandatory("error"or"warning")
) B0 ^" u* s6 U& q: c+ u! e
severity:"error", ~/ e/ x3 o0 M
//Mandatory8 W* k6 d' S Q
: t7 _& E- s5 @2 U6 }9 N+ S
message:"Invalidkeyword"
//Optional:themessageformattedwithsourcelocation
formattedMessage:"sourceFile.sol:100:Invalidkeyword"
}* Y+ {/ u/ g# ^
) v0 z8 G1 @8 t* R. _
],
; ]; h2 ~& r8 R1 G
//Thiscontainsthefile-leveloutputs.Incanbelimited/filteredbytheoutputSelectionsettings., u9 Q# I2 w- p! m3 i4 x
sources:{
"sourceFile.sol":{
' a8 O; W- z1 |2 ?
//Identifier(usedinsourcemaps)
id:1,
" v% S: u9 ^1 s2 @0 V3 C* a; X! H" N
//TheASTobject
ast:{},
//ThelegacyASTobject( L( d. O- f! B4 q% N5 M/ V
5 [& W" n! C% I( T/ C. p/ R! @
legacyAST:{}6 [4 j" d6 \8 s% v3 @) L; L
; U( P9 ], O' h- E* \' \
}
},. B7 W( h' E- P" E7 N# g. t
6 `/ E. q# u# ~' o
//Thiscontainsthecontract-leveloutputs.Itcanbelimited/filteredbytheoutputSelectionsettings.0 ]: T8 C- U; [2 b) Y" ^8 q6 |1 X
contracts:{. a* o5 @; {7 g# P% U. Z$ p
"sourceFile.sol":{
! _( u* u; e6 {! ^ E7 L; A/ r* j
//Ifthelanguageusedhasnocontractnames,thisfieldshouldequaltoanemptystring.
"ContractName":{- @! I0 ]9 M3 Y& I2 Y' e
5 ~0 b8 G4 J g; u6 I) D
//TheEthereumContractABI.Ifempty,itisrepresentedasanemptyarray.+ C/ o4 P* U3 z6 x( K
) W4 N9 n# s) h/ T2 E2 f
//Seehttps://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
abi:[], @4 M& @5 a( j3 r
//SeetheMetadataOutputdocumentation(serialisedJSONstring)6 N' V' M$ x2 w1 C0 X6 `7 N5 H) Q" A1 @5 N
metadata:"{...}",
//Userdocumentation(natspec), R4 p' ~! t6 j# ?! V( I- O7 D
userdoc:{},8 r& o; V9 W' \; R
& u; \, Y7 R3 z
//Developerdocumentation(natspec)
8 P" A$ W0 E$ Y: N" A7 @8 m
devdoc:{},. [6 @, _( ^+ W. g+ y1 f) k3 E
//Intermediaterepresentation(string)
8 \6 O+ _" |% H! w1 D. T
ir:"",
: g: H! m) k! j; L
//EVM-relatedoutputs( U9 p# f3 p! [2 C" ]
evm:{
//Assembly(string)) e5 j" _- o( t' G' W! @+ ?; ]5 v
* {0 a* d, V6 L
assembly:"",
1 Z- }; ]8 o# H% P1 h
//Old-styleassembly(object)
legacyAssembly:{},
//Bytecodeandrelateddetails.: s. d1 t4 R6 X- t( t f& V9 G+ n6 F
+ R7 S" L$ a7 ^' E9 n f+ c8 e
bytecode:{
//Thebytecodeasahexstring.
; w# g9 j8 l. s* ^
object:"00fe",
/ Y; V2 k7 q( A
//Opcodeslist(string). j3 i: k4 o+ g4 U6 g- q& G! g# n
& j: ?, X# S ^0 w* Z( w* P
opcodes:"",
4 `: b' u1 g/ y) A9 D7 W8 p- [
//Thesourcemappingasastring.Seethesourcemappingdefinition.
sourceMap:"",: I" B3 L+ d5 c( ]3 G
//Ifgiven,thisisanunlinkedobject.
9 j' W$ t/ h6 l/ }! j
linkReferences:{+ B: \* b9 s8 K+ p, o2 i! N
. B q8 Q( h# {. R' v* z
"libraryFile.sol":{
( T, K# c" z' q
//Byteoffsetsintothebytecode.Linkingreplacesthe20byteslocatedthere.
+ d. J+ z; |6 B. v( f- C
"Library1":[% t# U% t' f5 G9 ]
{start:0,length:20},
# V2 n/ V' k- R
{start:200,length:20}
]
1 Z9 I* E: ^1 Y1 p5 X
}
}
6 M3 D$ \4 f: n' l. E) m+ Y6 i/ c- q3 F
},
0 p0 S1 l+ @/ `) M
//Thesamelayoutasabove.
deployedBytecode:{},
1 Y. q0 V& N& H/ d
//Thelistoffunctionhashes0 ]1 e6 z& {$ {0 l) D5 B
methodIdentifiers:{
3 I5 d+ B6 [- v2 Y9 U+ d
"delegate(address)":"5c19a95c"
},, t& g4 w$ D* @" ?
. m3 V% \: i$ I$ J4 C
//Functiongasestimates
gasEstimates:{
1 U8 q2 K- t1 T: n7 \$ G
creation:{3 v" j) q: S" S& V: K4 I+ d& ]/ v
codeDepositCost:"420000",
@, l: X) a. `) y+ ?4 a0 |( A
executionCost:"infinite",
totalCost:"infinite"+ P! F9 g% s" \, ` C
4 X5 b- I) M* a P; _. S, X# p7 W% ]
},
external:{
"delegate(address)":"25000"
},
7 s, U3 W- O( @! @- m0 u: D0 M
internal:{
"heavyLifting()":"infinite"
' C3 Z& y* O& `# C% x
}
" a& S/ i9 i! \" u7 S
}5 K. V/ N5 p) r9 |& ^
},
//eWASMrelatedoutputs
ewasm:{- N. K+ i. _: y6 d6 A1 j
- K# X. r' N: { r
//S-expressionsformat
/ z# G4 A, |3 u
wast:"",
//Binaryformat(hexstring)
wasm:""
}" j+ G# f, M& ^
" g+ f6 {( k4 M3 [* E' I% b9 K( B
}3 F& R% f' c& ?3 u8 M3 c
}
5 i- r! w9 D6 J4 |4 B1 O5 c
}2 X# D3 f) b$ \3 h$ p
}4 ^% O& s% g3 @/ }8 k
错误类型说明:
0 `* n0 A# v8 P, x, x- g
JSONError:JSON错误,JSON输入不符合要求的格式,例如输入不是JSON对象,不支持语言,等等。/ I& l7 ?) X5 ^) B* Z0 _' r; P' X, e
IOError:IO错误,IO和导入处理错误,如提供的源中的不可解析URL或hash不匹配。
ParserError:语法f分析错误,源代码不符合语言规则。0 r4 }( F3 [* U
2 a2 c2 n+ j; O0 E2 A0 u
DocstringParsingError:文档解析错误,无法解析注释块中的NATSPEC标记。
SytRealError:语法错误,如continue在for循环之外使用。5 o/ ?- I% a J
1 f& [6 o `" x1 |+ w4 G
DeclarationError:声明错误,无效、不可解析或冲突的标识符名称。例如未找到标识符
TypeError:类型错误,如无效类型转换、无效赋值等。
( E# u6 q7 w; K) L
UnimplementedFeatureError:编译器不支持该特性,但希望在将来的版本中得到支持。. H$ Q4 @7 a; i5 {& A
InternalCompilerError:编译器中触发内部错误,这应该作为一个问题来反馈。& M- o+ G( T, N) g; i6 A; i1 Z4 V
" H* p) K( T! A% I, M
Exception:例外,编译过程中未知的故障,这应该作为一个问题反馈。
CompilerError:编译错误,编译器堆栈的使用无效,这应该作为一个问题来反馈。
- u# u% Y. z3 q: M% J
FatalError:致命错误,这应该作为一个问题来反馈。" F/ k2 v* b% M& X
' P/ [! A2 H9 ^ j: ^1 s: k
Warning:警告并没有停止编译,但如果可能的话,应该加以处理。( V3 I6 I& e+ w# s3 v+ F1 w3 V$ M5 s
& C% M$ S" Y$ v+ }
原文请访问:solc
* S+ n" K" V$ G9 }3 q- P
如果你希望马上开始学习以太坊DApp开发,推荐访问一个在线教程:* Z+ A, i- E- K! W( N0 S
以太坊智能合约,主要介绍智能合约与dapp应用开发,适合入门。
3 K7 o( r* Z# ?" B" S! I
以太坊开发,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
成为第一个吐槽的人