github.com/ethxdao/go-ethereum@v0.0.0-20221218102228-5ae34a9cc189/common/compiler/solidity.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package compiler wraps the ABI compilation outputs. 18 package compiler 19 20 import ( 21 "encoding/json" 22 "fmt" 23 ) 24 25 // --combined-output format 26 type solcOutput struct { 27 Contracts map[string]struct { 28 BinRuntime string `json:"bin-runtime"` 29 SrcMapRuntime string `json:"srcmap-runtime"` 30 Bin, SrcMap, Abi, Devdoc, Userdoc, Metadata string 31 Hashes map[string]string 32 } 33 Version string 34 } 35 36 // solidity v.0.8 changes the way ABI, Devdoc and Userdoc are serialized 37 type solcOutputV8 struct { 38 Contracts map[string]struct { 39 BinRuntime string `json:"bin-runtime"` 40 SrcMapRuntime string `json:"srcmap-runtime"` 41 Bin, SrcMap, Metadata string 42 Abi interface{} 43 Devdoc interface{} 44 Userdoc interface{} 45 Hashes map[string]string 46 } 47 Version string 48 } 49 50 // ParseCombinedJSON takes the direct output of a solc --combined-output run and 51 // parses it into a map of string contract name to Contract structs. The 52 // provided source, language and compiler version, and compiler options are all 53 // passed through into the Contract structs. 54 // 55 // The solc output is expected to contain ABI, source mapping, user docs, and dev docs. 56 // 57 // Returns an error if the JSON is malformed or missing data, or if the JSON 58 // embedded within the JSON is malformed. 59 func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) { 60 var output solcOutput 61 if err := json.Unmarshal(combinedJSON, &output); err != nil { 62 // Try to parse the output with the new solidity v.0.8.0 rules 63 return parseCombinedJSONV8(combinedJSON, source, languageVersion, compilerVersion, compilerOptions) 64 } 65 // Compilation succeeded, assemble and return the contracts. 66 contracts := make(map[string]*Contract) 67 for name, info := range output.Contracts { 68 // Parse the individual compilation results. 69 var abi, userdoc, devdoc interface{} 70 if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil { 71 return nil, fmt.Errorf("solc: error reading abi definition (%v)", err) 72 } 73 if err := json.Unmarshal([]byte(info.Userdoc), &userdoc); err != nil { 74 return nil, fmt.Errorf("solc: error reading userdoc definition (%v)", err) 75 } 76 if err := json.Unmarshal([]byte(info.Devdoc), &devdoc); err != nil { 77 return nil, fmt.Errorf("solc: error reading devdoc definition (%v)", err) 78 } 79 80 contracts[name] = &Contract{ 81 Code: "0x" + info.Bin, 82 RuntimeCode: "0x" + info.BinRuntime, 83 Hashes: info.Hashes, 84 Info: ContractInfo{ 85 Source: source, 86 Language: "Solidity", 87 LanguageVersion: languageVersion, 88 CompilerVersion: compilerVersion, 89 CompilerOptions: compilerOptions, 90 SrcMap: info.SrcMap, 91 SrcMapRuntime: info.SrcMapRuntime, 92 AbiDefinition: abi, 93 UserDoc: userdoc, 94 DeveloperDoc: devdoc, 95 Metadata: info.Metadata, 96 }, 97 } 98 } 99 return contracts, nil 100 } 101 102 // parseCombinedJSONV8 parses the direct output of solc --combined-output 103 // and parses it using the rules from solidity v.0.8.0 and later. 104 func parseCombinedJSONV8(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) { 105 var output solcOutputV8 106 if err := json.Unmarshal(combinedJSON, &output); err != nil { 107 return nil, err 108 } 109 // Compilation succeeded, assemble and return the contracts. 110 contracts := make(map[string]*Contract) 111 for name, info := range output.Contracts { 112 contracts[name] = &Contract{ 113 Code: "0x" + info.Bin, 114 RuntimeCode: "0x" + info.BinRuntime, 115 Hashes: info.Hashes, 116 Info: ContractInfo{ 117 Source: source, 118 Language: "Solidity", 119 LanguageVersion: languageVersion, 120 CompilerVersion: compilerVersion, 121 CompilerOptions: compilerOptions, 122 SrcMap: info.SrcMap, 123 SrcMapRuntime: info.SrcMapRuntime, 124 AbiDefinition: info.Abi, 125 UserDoc: info.Userdoc, 126 DeveloperDoc: info.Devdoc, 127 Metadata: info.Metadata, 128 }, 129 } 130 } 131 return contracts, nil 132 }