// Copyright 2015 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . // Package compiler wraps the ABI compilation outputs. package compiler import ( "encoding/json" "fmt" ) // --combined-output format type solcOutput struct { Contracts map[string]struct { BinRuntime string `json:"bin-runtime"` SrcMapRuntime string `json:"srcmap-runtime"` Bin, SrcMap, Abi, Devdoc, Userdoc, Metadata string Hashes map[string]string } 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 } // ParseCombinedJSON takes the direct output of a solc --combined-output run and // parses it into a map of string contract name to Contract structs. The // provided source, language and compiler version, and compiler options are all // passed through into the Contract structs. // // The solc output is expected to contain ABI, source mapping, user docs, and dev docs. // // Returns an error if the JSON is malformed or missing data, or if the JSON // embedded within the JSON is malformed. 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 { // 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) for name, info := range output.Contracts { // Parse the individual compilation results. var abi, userdoc, devdoc interface{} if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil { return nil, fmt.Errorf("solc: error reading abi definition (%v)", err) } if err := json.Unmarshal([]byte(info.Userdoc), &userdoc); err != nil { return nil, fmt.Errorf("solc: error reading userdoc definition (%v)", err) } if err := json.Unmarshal([]byte(info.Devdoc), &devdoc); err != nil { return nil, fmt.Errorf("solc: error reading devdoc definition (%v)", err) } 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: abi, UserDoc: userdoc, DeveloperDoc: devdoc, Metadata: info.Metadata, }, } } 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 }