@@ -25,20 +25,11 @@ import (
25
25
"io/ioutil"
26
26
"os/exec"
27
27
"regexp"
28
+ "strconv"
28
29
"strings"
29
-
30
- "github.com/ethereum/go-ethereum/common"
31
- "github.com/ethereum/go-ethereum/crypto"
32
30
)
33
31
34
- var (
35
- versionRegexp = regexp .MustCompile (`[0-9]+\.[0-9]+\.[0-9]+` )
36
- solcParams = []string {
37
- "--combined-json" , "bin,abi,userdoc,devdoc" ,
38
- "--add-std" , // include standard lib contracts
39
- "--optimize" , // code optimizer switched on
40
- }
41
- )
32
+ var versionRegexp = regexp .MustCompile (`([0-9]+)\.([0-9]+)\.([0-9]+)` )
42
33
43
34
type Contract struct {
44
35
Code string `json:"code"`
@@ -54,17 +45,33 @@ type ContractInfo struct {
54
45
AbiDefinition interface {} `json:"abiDefinition"`
55
46
UserDoc interface {} `json:"userDoc"`
56
47
DeveloperDoc interface {} `json:"developerDoc"`
48
+ Metadata string `json:"metadata"`
57
49
}
58
50
59
51
// Solidity contains information about the solidity compiler.
60
52
type Solidity struct {
61
53
Path , Version , FullVersion string
54
+ Major , Minor , Patch int
62
55
}
63
56
64
57
// --combined-output format
65
58
type solcOutput struct {
66
- Contracts map [string ]struct { Bin , Abi , Devdoc , Userdoc string }
67
- Version string
59
+ Contracts map [string ]struct {
60
+ Bin , Abi , Devdoc , Userdoc , Metadata string
61
+ }
62
+ Version string
63
+ }
64
+
65
+ func (s * Solidity ) makeArgs () []string {
66
+ p := []string {
67
+ "--combined-json" , "bin,abi,userdoc,devdoc" ,
68
+ "--add-std" , // include standard lib contracts
69
+ "--optimize" , // code optimizer switched on
70
+ }
71
+ if s .Major > 0 || s .Minor > 4 || s .Patch > 6 {
72
+ p [1 ] += ",metadata"
73
+ }
74
+ return p
68
75
}
69
76
70
77
// SolidityVersion runs solc and parses its version output.
@@ -75,13 +82,23 @@ func SolidityVersion(solc string) (*Solidity, error) {
75
82
var out bytes.Buffer
76
83
cmd := exec .Command (solc , "--version" )
77
84
cmd .Stdout = & out
78
- if err := cmd .Run (); err != nil {
85
+ err := cmd .Run ()
86
+ if err != nil {
87
+ return nil , err
88
+ }
89
+ matches := versionRegexp .FindStringSubmatch (out .String ())
90
+ if len (matches ) != 4 {
91
+ return nil , fmt .Errorf ("can't parse solc version %q" , out .String ())
92
+ }
93
+ s := & Solidity {Path : cmd .Path , FullVersion : out .String (), Version : matches [0 ]}
94
+ if s .Major , err = strconv .Atoi (matches [1 ]); err != nil {
79
95
return nil , err
80
96
}
81
- s := & Solidity {
82
- Path : cmd .Path ,
83
- FullVersion : out .String (),
84
- Version : versionRegexp .FindString (out .String ()),
97
+ if s .Minor , err = strconv .Atoi (matches [2 ]); err != nil {
98
+ return nil , err
99
+ }
100
+ if s .Patch , err = strconv .Atoi (matches [3 ]); err != nil {
101
+ return nil , err
85
102
}
86
103
return s , nil
87
104
}
@@ -91,13 +108,14 @@ func CompileSolidityString(solc, source string) (map[string]*Contract, error) {
91
108
if len (source ) == 0 {
92
109
return nil , errors .New ("solc: empty source string" )
93
110
}
94
- if solc == "" {
95
- solc = "solc"
111
+ s , err := SolidityVersion (solc )
112
+ if err != nil {
113
+ return nil , err
96
114
}
97
- args := append (solcParams , "--" )
98
- cmd := exec .Command (solc , append (args , "-" )... )
115
+ args := append (s . makeArgs () , "--" )
116
+ cmd := exec .Command (s . Path , append (args , "-" )... )
99
117
cmd .Stdin = strings .NewReader (source )
100
- return runsolc (cmd , source )
118
+ return s . run (cmd , source )
101
119
}
102
120
103
121
// CompileSolidity compiles all given Solidity source files.
@@ -109,15 +127,16 @@ func CompileSolidity(solc string, sourcefiles ...string) (map[string]*Contract,
109
127
if err != nil {
110
128
return nil , err
111
129
}
112
- if solc == "" {
113
- solc = "solc"
130
+ s , err := SolidityVersion (solc )
131
+ if err != nil {
132
+ return nil , err
114
133
}
115
- args := append (solcParams , "--" )
116
- cmd := exec .Command (solc , append (args , sourcefiles ... )... )
117
- return runsolc (cmd , source )
134
+ args := append (s . makeArgs () , "--" )
135
+ cmd := exec .Command (s . Path , append (args , sourcefiles ... )... )
136
+ return s . run (cmd , source )
118
137
}
119
138
120
- func runsolc (cmd * exec.Cmd , source string ) (map [string ]* Contract , error ) {
139
+ func ( s * Solidity ) run (cmd * exec.Cmd , source string ) (map [string ]* Contract , error ) {
121
140
var stderr , stdout bytes.Buffer
122
141
cmd .Stderr = & stderr
123
142
cmd .Stdout = & stdout
@@ -128,7 +147,6 @@ func runsolc(cmd *exec.Cmd, source string) (map[string]*Contract, error) {
128
147
if err := json .Unmarshal (stdout .Bytes (), & output ); err != nil {
129
148
return nil , err
130
149
}
131
- shortVersion := versionRegexp .FindString (output .Version )
132
150
133
151
// Compilation succeeded, assemble and return the contracts.
134
152
contracts := make (map [string ]* Contract )
@@ -151,12 +169,13 @@ func runsolc(cmd *exec.Cmd, source string) (map[string]*Contract, error) {
151
169
Info : ContractInfo {
152
170
Source : source ,
153
171
Language : "Solidity" ,
154
- LanguageVersion : shortVersion ,
155
- CompilerVersion : shortVersion ,
156
- CompilerOptions : strings .Join (solcParams , " " ),
172
+ LanguageVersion : s . Version ,
173
+ CompilerVersion : s . Version ,
174
+ CompilerOptions : strings .Join (s . makeArgs () , " " ),
157
175
AbiDefinition : abi ,
158
176
UserDoc : userdoc ,
159
177
DeveloperDoc : devdoc ,
178
+ Metadata : info .Metadata ,
160
179
},
161
180
}
162
181
}
@@ -174,13 +193,3 @@ func slurpFiles(files []string) (string, error) {
174
193
}
175
194
return concat .String (), nil
176
195
}
177
-
178
- // SaveInfo serializes info to the given file and returns its Keccak256 hash.
179
- func SaveInfo (info * ContractInfo , filename string ) (common.Hash , error ) {
180
- infojson , err := json .Marshal (info )
181
- if err != nil {
182
- return common.Hash {}, err
183
- }
184
- contenthash := common .BytesToHash (crypto .Keccak256 (infojson ))
185
- return contenthash , ioutil .WriteFile (filename , infojson , 0600 )
186
- }
0 commit comments