cmd/abigen: refactor command line interface (#19797)
* cmd, common: refactor abigen command line interface * cmd/abigen: address comment
This commit is contained in:
		
							parent
							
								
									cdfe9a3a2a
								
							
						
					
					
						commit
						22060611fb
					
				| @ -18,63 +18,129 @@ package main | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"flag" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	"github.com/ethereum/go-ethereum/accounts/abi/bind" | 	"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||||||
|  | 	"github.com/ethereum/go-ethereum/cmd/utils" | ||||||
| 	"github.com/ethereum/go-ethereum/common/compiler" | 	"github.com/ethereum/go-ethereum/common/compiler" | ||||||
| 	"github.com/ethereum/go-ethereum/crypto" | 	"github.com/ethereum/go-ethereum/crypto" | ||||||
|  | 	"github.com/ethereum/go-ethereum/log" | ||||||
|  | 	"gopkg.in/urfave/cli.v1" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	commandHelperTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...] | ||||||
|  | {{if .Description}}{{.Description}} | ||||||
|  | {{end}}{{if .Subcommands}} | ||||||
|  | SUBCOMMANDS: | ||||||
|  | 	{{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} | ||||||
|  | 	{{end}}{{end}}{{if .Flags}} | ||||||
|  | OPTIONS: | ||||||
|  | {{range $.Flags}}{{"\t"}}{{.}} | ||||||
|  | {{end}} | ||||||
|  | {{end}}` | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var ( | var ( | ||||||
| 	abiFlag = flag.String("abi", "", "Path to the Ethereum contract ABI json to bind, - for STDIN") | 	// Git SHA1 commit hash of the release (set via linker flags)
 | ||||||
| 	binFlag = flag.String("bin", "", "Path to the Ethereum contract bytecode (generate deploy method)") | 	gitCommit = "" | ||||||
| 	typFlag = flag.String("type", "", "Struct name for the binding (default = package name)") | 	gitDate   = "" | ||||||
| 
 | 
 | ||||||
| 	solFlag  = flag.String("sol", "", "Path to the Ethereum contract Solidity source to build and bind") | 	app *cli.App | ||||||
| 	solcFlag = flag.String("solc", "solc", "Solidity compiler to use if source builds are requested") |  | ||||||
| 	excFlag  = flag.String("exc", "", "Comma separated types to exclude from binding") |  | ||||||
| 
 | 
 | ||||||
| 	vyFlag    = flag.String("vy", "", "Path to the Ethereum contract Vyper source to build and bind") | 	// Flags needed by abigen
 | ||||||
| 	vyperFlag = flag.String("vyper", "vyper", "Vyper compiler to use if source builds are requested") | 	abiFlag = cli.StringFlag{ | ||||||
| 
 | 		Name:  "abi", | ||||||
| 	pkgFlag  = flag.String("pkg", "", "Package name to generate the binding into") | 		Usage: "Path to the Ethereum contract ABI json to bind, - for STDIN", | ||||||
| 	outFlag  = flag.String("out", "", "Output file for the generated binding (default = stdout)") | 	} | ||||||
| 	langFlag = flag.String("lang", "go", "Destination language for the bindings (go, java, objc)") | 	binFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "bin", | ||||||
|  | 		Usage: "Path to the Ethereum contract bytecode (generate deploy method)", | ||||||
|  | 	} | ||||||
|  | 	typeFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "type", | ||||||
|  | 		Usage: "Struct name for the binding (default = package name)", | ||||||
|  | 	} | ||||||
|  | 	jsonFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "combined-json", | ||||||
|  | 		Usage: "Path to the combined-json file generated by compiler", | ||||||
|  | 	} | ||||||
|  | 	solFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "sol", | ||||||
|  | 		Usage: "Path to the Ethereum contract Solidity source to build and bind", | ||||||
|  | 	} | ||||||
|  | 	solcFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "solc", | ||||||
|  | 		Usage: "Solidity compiler to use if source builds are requested", | ||||||
|  | 		Value: "solc", | ||||||
|  | 	} | ||||||
|  | 	vyFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "vy", | ||||||
|  | 		Usage: "Path to the Ethereum contract Vyper source to build and bind", | ||||||
|  | 	} | ||||||
|  | 	vyperFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "vyper", | ||||||
|  | 		Usage: "Vyper compiler to use if source builds are requested", | ||||||
|  | 		Value: "vyper", | ||||||
|  | 	} | ||||||
|  | 	excFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "exc", | ||||||
|  | 		Usage: "Comma separated types to exclude from binding", | ||||||
|  | 	} | ||||||
|  | 	pkgFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "pkg", | ||||||
|  | 		Usage: "Package name to generate the binding into", | ||||||
|  | 	} | ||||||
|  | 	outFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "out", | ||||||
|  | 		Usage: "Output file for the generated binding (default = stdout)", | ||||||
|  | 	} | ||||||
|  | 	langFlag = cli.StringFlag{ | ||||||
|  | 		Name:  "lang", | ||||||
|  | 		Usage: "Destination language for the bindings (go, java, objc)", | ||||||
|  | 		Value: "go", | ||||||
|  | 	} | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func main() { | func init() { | ||||||
| 	// Parse and ensure all needed inputs are specified
 | 	app = utils.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool") | ||||||
| 	flag.Parse() | 	app.Flags = []cli.Flag{ | ||||||
| 
 | 		abiFlag, | ||||||
| 	if *abiFlag == "" && *solFlag == "" && *vyFlag == "" { | 		binFlag, | ||||||
| 		fmt.Printf("No contract ABI (--abi), Solidity source (--sol), or Vyper source (--vy) specified\n") | 		typeFlag, | ||||||
| 		os.Exit(-1) | 		jsonFlag, | ||||||
| 	} else if (*abiFlag != "" || *binFlag != "" || *typFlag != "") && (*solFlag != "" || *vyFlag != "") { | 		solFlag, | ||||||
| 		fmt.Printf("Contract ABI (--abi), bytecode (--bin) and type (--type) flags are mutually exclusive with the Solidity (--sol) and Vyper (--vy) flags\n") | 		solcFlag, | ||||||
| 		os.Exit(-1) | 		vyFlag, | ||||||
| 	} else if *solFlag != "" && *vyFlag != "" { | 		vyperFlag, | ||||||
| 		fmt.Printf("Solidity (--sol) and Vyper (--vy) flags are mutually exclusive\n") | 		excFlag, | ||||||
| 		os.Exit(-1) | 		pkgFlag, | ||||||
|  | 		outFlag, | ||||||
|  | 		langFlag, | ||||||
| 	} | 	} | ||||||
| 	if *pkgFlag == "" { | 	app.Action = utils.MigrateFlags(abigen) | ||||||
| 		fmt.Printf("No destination package specified (--pkg)\n") | 	cli.CommandHelpTemplate = commandHelperTemplate | ||||||
| 		os.Exit(-1) | } | ||||||
|  | 
 | ||||||
|  | func abigen(c *cli.Context) error { | ||||||
|  | 	utils.CheckExclusive(c, abiFlag, jsonFlag, solFlag, vyFlag) // Only one source can be selected.
 | ||||||
|  | 	if c.GlobalString(pkgFlag.Name) == "" { | ||||||
|  | 		utils.Fatalf("No destination package specified (--pkg)") | ||||||
| 	} | 	} | ||||||
| 	var lang bind.Lang | 	var lang bind.Lang | ||||||
| 	switch *langFlag { | 	switch c.GlobalString(langFlag.Name) { | ||||||
| 	case "go": | 	case "go": | ||||||
| 		lang = bind.LangGo | 		lang = bind.LangGo | ||||||
| 	case "java": | 	case "java": | ||||||
| 		lang = bind.LangJava | 		lang = bind.LangJava | ||||||
| 	case "objc": | 	case "objc": | ||||||
| 		lang = bind.LangObjC | 		lang = bind.LangObjC | ||||||
|  | 		utils.Fatalf("Objc binding generation is uncompleted") | ||||||
| 	default: | 	default: | ||||||
| 		fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", *langFlag) | 		utils.Fatalf("Unsupported destination language \"%s\" (--lang)", c.GlobalString(langFlag.Name)) | ||||||
| 		os.Exit(-1) |  | ||||||
| 	} | 	} | ||||||
| 	// If the entire solidity code was specified, build and bind based on that
 | 	// If the entire solidity code was specified, build and bind based on that
 | ||||||
| 	var ( | 	var ( | ||||||
| @ -84,34 +150,67 @@ func main() { | |||||||
| 		sigs  []map[string]string | 		sigs  []map[string]string | ||||||
| 		libs  = make(map[string]string) | 		libs  = make(map[string]string) | ||||||
| 	) | 	) | ||||||
| 	if *solFlag != "" || *vyFlag != "" || *abiFlag == "-" { | 	if c.GlobalString(abiFlag.Name) != "" { | ||||||
|  | 		// Load up the ABI, optional bytecode and type name from the parameters
 | ||||||
|  | 		var ( | ||||||
|  | 			abi []byte | ||||||
|  | 			err error | ||||||
|  | 		) | ||||||
|  | 		input := c.GlobalString(abiFlag.Name) | ||||||
|  | 		if input == "-" { | ||||||
|  | 			abi, err = ioutil.ReadAll(os.Stdin) | ||||||
|  | 		} else { | ||||||
|  | 			abi, err = ioutil.ReadFile(input) | ||||||
|  | 		} | ||||||
|  | 		if err != nil { | ||||||
|  | 			utils.Fatalf("Failed to read input ABI: %v", err) | ||||||
|  | 		} | ||||||
|  | 		abis = append(abis, string(abi)) | ||||||
|  | 
 | ||||||
|  | 		var bin []byte | ||||||
|  | 		if binFile := c.GlobalString(binFlag.Name); binFile != "" { | ||||||
|  | 			if bin, err = ioutil.ReadFile(binFile); err != nil { | ||||||
|  | 				utils.Fatalf("Failed to read input bytecode: %v", err) | ||||||
|  | 			} | ||||||
|  | 			if strings.Contains(string(bin), "//") { | ||||||
|  | 				utils.Fatalf("Contract has additional library references, please use other mode(e.g. --combined-json) to catch library infos") | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		bins = append(bins, string(bin)) | ||||||
|  | 
 | ||||||
|  | 		kind := c.GlobalString(typeFlag.Name) | ||||||
|  | 		if kind == "" { | ||||||
|  | 			kind = c.GlobalString(pkgFlag.Name) | ||||||
|  | 		} | ||||||
|  | 		types = append(types, kind) | ||||||
|  | 	} else { | ||||||
| 		// Generate the list of types to exclude from binding
 | 		// Generate the list of types to exclude from binding
 | ||||||
| 		exclude := make(map[string]bool) | 		exclude := make(map[string]bool) | ||||||
| 		for _, kind := range strings.Split(*excFlag, ",") { | 		for _, kind := range strings.Split(c.GlobalString(excFlag.Name), ",") { | ||||||
| 			exclude[strings.ToLower(kind)] = true | 			exclude[strings.ToLower(kind)] = true | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		var contracts map[string]*compiler.Contract |  | ||||||
| 		var err error | 		var err error | ||||||
|  | 		var contracts map[string]*compiler.Contract | ||||||
| 
 | 
 | ||||||
| 		switch { | 		switch { | ||||||
| 		case *solFlag != "": | 		case c.GlobalIsSet(solFlag.Name): | ||||||
| 			contracts, err = compiler.CompileSolidity(*solcFlag, *solFlag) | 			contracts, err = compiler.CompileSolidity(c.GlobalString(solcFlag.Name), c.GlobalString(solFlag.Name)) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				fmt.Printf("Failed to build Solidity contract: %v\n", err) | 				utils.Fatalf("Failed to build Solidity contract: %v", err) | ||||||
| 				os.Exit(-1) |  | ||||||
| 			} | 			} | ||||||
| 		case *vyFlag != "": | 		case c.GlobalIsSet(vyFlag.Name): | ||||||
| 			contracts, err = compiler.CompileVyper(*vyperFlag, *vyFlag) | 			contracts, err = compiler.CompileVyper(c.GlobalString(vyperFlag.Name), c.GlobalString(vyFlag.Name)) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				fmt.Printf("Failed to build Vyper contract: %v\n", err) | 				utils.Fatalf("Failed to build Vyper contract: %v", err) | ||||||
| 				os.Exit(-1) |  | ||||||
| 			} | 			} | ||||||
| 		default: | 		case c.GlobalIsSet(jsonFlag.Name): | ||||||
| 			contracts, err = contractsFromStdin() | 			jsonOutput, err := ioutil.ReadFile(c.GlobalString(jsonFlag.Name)) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				fmt.Printf("Failed to read input ABIs from STDIN: %v\n", err) | 				utils.Fatalf("Failed to read combined-json from compiler: %v", err) | ||||||
| 				os.Exit(-1) | 			} | ||||||
|  | 			contracts, err = compiler.ParseCombinedJSON(jsonOutput, "", "", "", "") | ||||||
|  | 			if err != nil { | ||||||
|  | 				utils.Fatalf("Failed to read contract information from json output: %v", err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		// Gather all non-excluded contract for binding
 | 		// Gather all non-excluded contract for binding
 | ||||||
| @ -121,65 +220,39 @@ func main() { | |||||||
| 			} | 			} | ||||||
| 			abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse
 | 			abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse
 | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				fmt.Printf("Failed to parse ABIs from compiler output: %v\n", err) | 				utils.Fatalf("Failed to parse ABIs from compiler output: %v", err) | ||||||
| 				os.Exit(-1) |  | ||||||
| 			} | 			} | ||||||
| 			abis = append(abis, string(abi)) | 			abis = append(abis, string(abi)) | ||||||
| 			bins = append(bins, contract.Code) | 			bins = append(bins, contract.Code) | ||||||
| 			sigs = append(sigs, contract.Hashes) | 			sigs = append(sigs, contract.Hashes) | ||||||
| 
 |  | ||||||
| 			nameParts := strings.Split(name, ":") | 			nameParts := strings.Split(name, ":") | ||||||
| 			types = append(types, nameParts[len(nameParts)-1]) | 			types = append(types, nameParts[len(nameParts)-1]) | ||||||
| 
 | 
 | ||||||
| 			libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] | 			libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] | ||||||
| 			libs[libPattern] = nameParts[len(nameParts)-1] | 			libs[libPattern] = nameParts[len(nameParts)-1] | ||||||
| 		} | 		} | ||||||
| 	} else { |  | ||||||
| 		// Otherwise load up the ABI, optional bytecode and type name from the parameters
 |  | ||||||
| 		abi, err := ioutil.ReadFile(*abiFlag) |  | ||||||
| 
 |  | ||||||
| 		if err != nil { |  | ||||||
| 			fmt.Printf("Failed to read input ABI: %v\n", err) |  | ||||||
| 			os.Exit(-1) |  | ||||||
| 		} |  | ||||||
| 		abis = append(abis, string(abi)) |  | ||||||
| 
 |  | ||||||
| 		var bin []byte |  | ||||||
| 		if *binFlag != "" { |  | ||||||
| 			if bin, err = ioutil.ReadFile(*binFlag); err != nil { |  | ||||||
| 				fmt.Printf("Failed to read input bytecode: %v\n", err) |  | ||||||
| 				os.Exit(-1) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		bins = append(bins, string(bin)) |  | ||||||
| 
 |  | ||||||
| 		kind := *typFlag |  | ||||||
| 		if kind == "" { |  | ||||||
| 			kind = *pkgFlag |  | ||||||
| 		} |  | ||||||
| 		types = append(types, kind) |  | ||||||
| 	} | 	} | ||||||
| 	// Generate the contract binding
 | 	// Generate the contract binding
 | ||||||
| 	code, err := bind.Bind(types, abis, bins, sigs, *pkgFlag, lang, libs) | 	code, err := bind.Bind(types, abis, bins, sigs, c.GlobalString(pkgFlag.Name), lang, libs) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		fmt.Printf("Failed to generate ABI binding: %v\n", err) | 		utils.Fatalf("Failed to generate ABI binding: %v", err) | ||||||
| 		os.Exit(-1) |  | ||||||
| 	} | 	} | ||||||
| 	// Either flush it out to a file or display on the standard output
 | 	// Either flush it out to a file or display on the standard output
 | ||||||
| 	if *outFlag == "" { | 	if !c.GlobalIsSet(outFlag.Name) { | ||||||
| 		fmt.Printf("%s\n", code) | 		fmt.Printf("%s\n", code) | ||||||
| 		return | 		return nil | ||||||
| 	} | 	} | ||||||
| 	if err := ioutil.WriteFile(*outFlag, []byte(code), 0600); err != nil { | 	if err := ioutil.WriteFile(c.GlobalString(outFlag.Name), []byte(code), 0600); err != nil { | ||||||
| 		fmt.Printf("Failed to write ABI binding: %v\n", err) | 		utils.Fatalf("Failed to write ABI binding: %v", err) | ||||||
| 		os.Exit(-1) |  | ||||||
| 	} | 	} | ||||||
|  | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func contractsFromStdin() (map[string]*compiler.Contract, error) { | func main() { | ||||||
| 	bytes, err := ioutil.ReadAll(os.Stdin) | 	log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) | ||||||
| 	if err != nil { | 
 | ||||||
| 		return nil, err | 	if err := app.Run(os.Args); err != nil { | ||||||
|  | 		fmt.Fprintln(os.Stderr, err) | ||||||
|  | 		os.Exit(1) | ||||||
| 	} | 	} | ||||||
| 	return compiler.ParseCombinedJSON(bytes, "", "", "", "") |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -944,7 +944,7 @@ func setWS(ctx *cli.Context, cfg *node.Config) { | |||||||
| // setIPC creates an IPC path configuration from the set command line flags,
 | // setIPC creates an IPC path configuration from the set command line flags,
 | ||||||
| // returning an empty string if IPC was explicitly disabled, or the set path.
 | // returning an empty string if IPC was explicitly disabled, or the set path.
 | ||||||
| func setIPC(ctx *cli.Context, cfg *node.Config) { | func setIPC(ctx *cli.Context, cfg *node.Config) { | ||||||
| 	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag) | 	CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag) | ||||||
| 	switch { | 	switch { | ||||||
| 	case ctx.GlobalBool(IPCDisabledFlag.Name): | 	case ctx.GlobalBool(IPCDisabledFlag.Name): | ||||||
| 		cfg.IPCPath = "" | 		cfg.IPCPath = "" | ||||||
| @ -1329,10 +1329,10 @@ func setWhitelist(ctx *cli.Context, cfg *eth.Config) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // checkExclusive verifies that only a single instance of the provided flags was
 | // CheckExclusive verifies that only a single instance of the provided flags was
 | ||||||
| // set by the user. Each flag might optionally be followed by a string type to
 | // set by the user. Each flag might optionally be followed by a string type to
 | ||||||
| // specialize it further.
 | // specialize it further.
 | ||||||
| func checkExclusive(ctx *cli.Context, args ...interface{}) { | func CheckExclusive(ctx *cli.Context, args ...interface{}) { | ||||||
| 	set := make([]string, 0, 1) | 	set := make([]string, 0, 1) | ||||||
| 	for i := 0; i < len(args); i++ { | 	for i := 0; i < len(args); i++ { | ||||||
| 		// Make sure the next argument is a flag and skip if not set
 | 		// Make sure the next argument is a flag and skip if not set
 | ||||||
| @ -1386,10 +1386,10 @@ func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) { | |||||||
| // SetEthConfig applies eth-related command line flags to the config.
 | // SetEthConfig applies eth-related command line flags to the config.
 | ||||||
| func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { | func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { | ||||||
| 	// Avoid conflicting network flags
 | 	// Avoid conflicting network flags
 | ||||||
| 	checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag, GoerliFlag) | 	CheckExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag, GoerliFlag) | ||||||
| 	checkExclusive(ctx, LightServFlag, SyncModeFlag, "light") | 	CheckExclusive(ctx, LightServFlag, SyncModeFlag, "light") | ||||||
| 	// Can't use both ephemeral unlocked and external signer
 | 	// Can't use both ephemeral unlocked and external signer
 | ||||||
| 	checkExclusive(ctx, DeveloperFlag, ExternalSignerFlag) | 	CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) | ||||||
| 	var ks *keystore.KeyStore | 	var ks *keystore.KeyStore | ||||||
| 	if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { | 	if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { | ||||||
| 		ks = keystores[0].(*keystore.KeyStore) | 		ks = keystores[0].(*keystore.KeyStore) | ||||||
|  | |||||||
| @ -142,7 +142,6 @@ func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion strin | |||||||
| 	if err := json.Unmarshal(combinedJSON, &output); err != nil { | 	if err := json.Unmarshal(combinedJSON, &output); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	// Compilation succeeded, assemble and return the contracts.
 | 	// Compilation succeeded, assemble and return the contracts.
 | ||||||
| 	contracts := make(map[string]*Contract) | 	contracts := make(map[string]*Contract) | ||||||
| 	for name, info := range output.Contracts { | 	for name, info := range output.Contracts { | ||||||
| @ -151,14 +150,10 @@ func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion strin | |||||||
| 		if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil { | 		if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil { | ||||||
| 			return nil, fmt.Errorf("solc: error reading abi definition (%v)", err) | 			return nil, fmt.Errorf("solc: error reading abi definition (%v)", err) | ||||||
| 		} | 		} | ||||||
| 		var userdoc interface{} | 		var userdoc, devdoc interface{} | ||||||
| 		if err := json.Unmarshal([]byte(info.Userdoc), &userdoc); err != nil { | 		json.Unmarshal([]byte(info.Userdoc), &userdoc) | ||||||
| 			return nil, fmt.Errorf("solc: error reading user doc: %v", err) | 		json.Unmarshal([]byte(info.Devdoc), &devdoc) | ||||||
| 		} | 
 | ||||||
| 		var devdoc interface{} |  | ||||||
| 		if err := json.Unmarshal([]byte(info.Devdoc), &devdoc); err != nil { |  | ||||||
| 			return nil, fmt.Errorf("solc: error reading dev doc: %v", err) |  | ||||||
| 		} |  | ||||||
| 		contracts[name] = &Contract{ | 		contracts[name] = &Contract{ | ||||||
| 			Code:        "0x" + info.Bin, | 			Code:        "0x" + info.Bin, | ||||||
| 			RuntimeCode: "0x" + info.BinRuntime, | 			RuntimeCode: "0x" + info.BinRuntime, | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user