소스 검색

common/compiler: fix parsing of solc output with solidity v.0.8.0 (#22092)

Solidity 0.8.0 changes the way that output is marshalled. This patch allows to parse both
the legacy format used previously and the new format.

See also https://docs.soliditylang.org/en/breaking/080-breaking-changes.html#interface-changes
Marius van der Wijden 4 년 전
부모
커밋
9ba306d47e
1개의 변경된 파일48개의 추가작업 그리고 2개의 파일을 삭제
  1. 48 2
      common/compiler/solidity.go

+ 48 - 2
common/compiler/solidity.go

@@ -44,6 +44,20 @@ type solcOutput struct {
 	Version string
 }
 
+// solidity v.0.8 changes the way ABI, Devdoc and Userdoc are serialized
+type solcOutputV8 struct {
+	Contracts map[string]struct {
+		BinRuntime            string `json:"bin-runtime"`
+		SrcMapRuntime         string `json:"srcmap-runtime"`
+		Bin, SrcMap, Metadata string
+		Abi                   interface{}
+		Devdoc                interface{}
+		Userdoc               interface{}
+		Hashes                map[string]string
+	}
+	Version string
+}
+
 func (s *Solidity) makeArgs() []string {
 	p := []string{
 		"--combined-json", "bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc",
@@ -125,7 +139,6 @@ func (s *Solidity) run(cmd *exec.Cmd, source string) (map[string]*Contract, erro
 	if err := cmd.Run(); err != nil {
 		return nil, fmt.Errorf("solc: %v\n%s", err, stderr.Bytes())
 	}
-
 	return ParseCombinedJSON(stdout.Bytes(), source, s.Version, s.Version, strings.Join(s.makeArgs(), " "))
 }
 
@@ -141,7 +154,8 @@ func (s *Solidity) run(cmd *exec.Cmd, source string) (map[string]*Contract, erro
 func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) {
 	var output solcOutput
 	if err := json.Unmarshal(combinedJSON, &output); err != nil {
-		return nil, err
+		// Try to parse the output with the new solidity v.0.8.0 rules
+		return parseCombinedJSONV8(combinedJSON, source, languageVersion, compilerVersion, compilerOptions)
 	}
 	// Compilation succeeded, assemble and return the contracts.
 	contracts := make(map[string]*Contract)
@@ -176,3 +190,35 @@ func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion strin
 	}
 	return contracts, nil
 }
+
+// parseCombinedJSONV8 parses the direct output of solc --combined-output
+// and parses it using the rules from solidity v.0.8.0 and later.
+func parseCombinedJSONV8(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) {
+	var output solcOutputV8
+	if err := json.Unmarshal(combinedJSON, &output); err != nil {
+		return nil, err
+	}
+	// Compilation succeeded, assemble and return the contracts.
+	contracts := make(map[string]*Contract)
+	for name, info := range output.Contracts {
+		contracts[name] = &Contract{
+			Code:        "0x" + info.Bin,
+			RuntimeCode: "0x" + info.BinRuntime,
+			Hashes:      info.Hashes,
+			Info: ContractInfo{
+				Source:          source,
+				Language:        "Solidity",
+				LanguageVersion: languageVersion,
+				CompilerVersion: compilerVersion,
+				CompilerOptions: compilerOptions,
+				SrcMap:          info.SrcMap,
+				SrcMapRuntime:   info.SrcMapRuntime,
+				AbiDefinition:   info.Abi,
+				UserDoc:         info.Userdoc,
+				DeveloperDoc:    info.Devdoc,
+				Metadata:        info.Metadata,
+			},
+		}
+	}
+	return contracts, nil
+}