diff --git a/cmd/abigen/main.go b/cmd/abigen/main.go
index aaf2f9fa864234f6244fab4785e27adec222f2b7..6af34c5fe8e37efa374268d07ba09736054b1312 100644
--- a/cmd/abigen/main.go
+++ b/cmd/abigen/main.go
@@ -18,63 +18,129 @@ package main
 
 import (
 	"encoding/json"
-	"flag"
 	"fmt"
 	"io/ioutil"
 	"os"
 	"strings"
 
 	"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/crypto"
+	"github.com/ethereum/go-ethereum/log"
+	"gopkg.in/urfave/cli.v1"
 )
 
-var (
-	abiFlag = flag.String("abi", "", "Path to the Ethereum contract ABI json to bind, - for STDIN")
-	binFlag = flag.String("bin", "", "Path to the Ethereum contract bytecode (generate deploy method)")
-	typFlag = flag.String("type", "", "Struct name for the binding (default = package name)")
+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}}`
+)
 
-	solFlag  = flag.String("sol", "", "Path to the Ethereum contract Solidity source to build and bind")
-	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")
+var (
+	// Git SHA1 commit hash of the release (set via linker flags)
+	gitCommit = ""
+	gitDate   = ""
 
-	vyFlag    = flag.String("vy", "", "Path to the Ethereum contract Vyper source to build and bind")
-	vyperFlag = flag.String("vyper", "vyper", "Vyper compiler to use if source builds are requested")
+	app *cli.App
 
-	pkgFlag  = flag.String("pkg", "", "Package name to generate the binding into")
-	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)")
+	// Flags needed by abigen
+	abiFlag = cli.StringFlag{
+		Name:  "abi",
+		Usage: "Path to the Ethereum contract ABI json to bind, - for STDIN",
+	}
+	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() {
-	// Parse and ensure all needed inputs are specified
-	flag.Parse()
+func init() {
+	app = utils.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool")
+	app.Flags = []cli.Flag{
+		abiFlag,
+		binFlag,
+		typeFlag,
+		jsonFlag,
+		solFlag,
+		solcFlag,
+		vyFlag,
+		vyperFlag,
+		excFlag,
+		pkgFlag,
+		outFlag,
+		langFlag,
+	}
+	app.Action = utils.MigrateFlags(abigen)
+	cli.CommandHelpTemplate = commandHelperTemplate
+}
 
-	if *abiFlag == "" && *solFlag == "" && *vyFlag == "" {
-		fmt.Printf("No contract ABI (--abi), Solidity source (--sol), or Vyper source (--vy) specified\n")
-		os.Exit(-1)
-	} else if (*abiFlag != "" || *binFlag != "" || *typFlag != "") && (*solFlag != "" || *vyFlag != "") {
-		fmt.Printf("Contract ABI (--abi), bytecode (--bin) and type (--type) flags are mutually exclusive with the Solidity (--sol) and Vyper (--vy) flags\n")
-		os.Exit(-1)
-	} else if *solFlag != "" && *vyFlag != "" {
-		fmt.Printf("Solidity (--sol) and Vyper (--vy) flags are mutually exclusive\n")
-		os.Exit(-1)
-	}
-	if *pkgFlag == "" {
-		fmt.Printf("No destination package specified (--pkg)\n")
-		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
-	switch *langFlag {
+	switch c.GlobalString(langFlag.Name) {
 	case "go":
 		lang = bind.LangGo
 	case "java":
 		lang = bind.LangJava
 	case "objc":
 		lang = bind.LangObjC
+		utils.Fatalf("Objc binding generation is uncompleted")
 	default:
-		fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", *langFlag)
-		os.Exit(-1)
+		utils.Fatalf("Unsupported destination language \"%s\" (--lang)", c.GlobalString(langFlag.Name))
 	}
 	// If the entire solidity code was specified, build and bind based on that
 	var (
@@ -84,34 +150,67 @@ func main() {
 		sigs  []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
 		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
 		}
-
-		var contracts map[string]*compiler.Contract
 		var err error
+		var contracts map[string]*compiler.Contract
 
 		switch {
-		case *solFlag != "":
-			contracts, err = compiler.CompileSolidity(*solcFlag, *solFlag)
+		case c.GlobalIsSet(solFlag.Name):
+			contracts, err = compiler.CompileSolidity(c.GlobalString(solcFlag.Name), c.GlobalString(solFlag.Name))
+			if err != nil {
+				utils.Fatalf("Failed to build Solidity contract: %v", err)
+			}
+		case c.GlobalIsSet(vyFlag.Name):
+			contracts, err = compiler.CompileVyper(c.GlobalString(vyperFlag.Name), c.GlobalString(vyFlag.Name))
 			if err != nil {
-				fmt.Printf("Failed to build Solidity contract: %v\n", err)
-				os.Exit(-1)
+				utils.Fatalf("Failed to build Vyper contract: %v", err)
 			}
-		case *vyFlag != "":
-			contracts, err = compiler.CompileVyper(*vyperFlag, *vyFlag)
+		case c.GlobalIsSet(jsonFlag.Name):
+			jsonOutput, err := ioutil.ReadFile(c.GlobalString(jsonFlag.Name))
 			if err != nil {
-				fmt.Printf("Failed to build Vyper contract: %v\n", err)
-				os.Exit(-1)
+				utils.Fatalf("Failed to read combined-json from compiler: %v", err)
 			}
-		default:
-			contracts, err = contractsFromStdin()
+			contracts, err = compiler.ParseCombinedJSON(jsonOutput, "", "", "", "")
 			if err != nil {
-				fmt.Printf("Failed to read input ABIs from STDIN: %v\n", err)
-				os.Exit(-1)
+				utils.Fatalf("Failed to read contract information from json output: %v", err)
 			}
 		}
 		// Gather all non-excluded contract for binding
@@ -121,65 +220,39 @@ func main() {
 			}
 			abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse
 			if err != nil {
-				fmt.Printf("Failed to parse ABIs from compiler output: %v\n", err)
-				os.Exit(-1)
+				utils.Fatalf("Failed to parse ABIs from compiler output: %v", err)
 			}
 			abis = append(abis, string(abi))
 			bins = append(bins, contract.Code)
 			sigs = append(sigs, contract.Hashes)
-
 			nameParts := strings.Split(name, ":")
 			types = append(types, nameParts[len(nameParts)-1])
 
 			libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36]
 			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
-	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 {
-		fmt.Printf("Failed to generate ABI binding: %v\n", err)
-		os.Exit(-1)
+		utils.Fatalf("Failed to generate ABI binding: %v", err)
 	}
 	// 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)
-		return
+		return nil
 	}
-	if err := ioutil.WriteFile(*outFlag, []byte(code), 0600); err != nil {
-		fmt.Printf("Failed to write ABI binding: %v\n", err)
-		os.Exit(-1)
+	if err := ioutil.WriteFile(c.GlobalString(outFlag.Name), []byte(code), 0600); err != nil {
+		utils.Fatalf("Failed to write ABI binding: %v", err)
 	}
+	return nil
 }
 
-func contractsFromStdin() (map[string]*compiler.Contract, error) {
-	bytes, err := ioutil.ReadAll(os.Stdin)
-	if err != nil {
-		return nil, err
+func main() {
+	log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+
+	if err := app.Run(os.Args); err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
 	}
-	return compiler.ParseCombinedJSON(bytes, "", "", "", "")
 }
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index f928edc0f797eba37dbec90d9d40a473c9b9f119..9a92e21fe9b52db4fe15e896ea268804a3ab8450 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -944,7 +944,7 @@ func setWS(ctx *cli.Context, cfg *node.Config) {
 // 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.
 func setIPC(ctx *cli.Context, cfg *node.Config) {
-	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
+	CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
 	switch {
 	case ctx.GlobalBool(IPCDisabledFlag.Name):
 		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
 // specialize it further.
-func checkExclusive(ctx *cli.Context, args ...interface{}) {
+func CheckExclusive(ctx *cli.Context, args ...interface{}) {
 	set := make([]string, 0, 1)
 	for i := 0; i < len(args); i++ {
 		// 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.
 func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
 	// Avoid conflicting network flags
-	checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag, GoerliFlag)
-	checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")
+	CheckExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag, GoerliFlag)
+	CheckExclusive(ctx, LightServFlag, SyncModeFlag, "light")
 	// Can't use both ephemeral unlocked and external signer
-	checkExclusive(ctx, DeveloperFlag, ExternalSignerFlag)
+	CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag)
 	var ks *keystore.KeyStore
 	if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
 		ks = keystores[0].(*keystore.KeyStore)
diff --git a/common/compiler/solidity.go b/common/compiler/solidity.go
index 56e01ee334ca05c0248ae3f12145574e4a9200c4..16b91bf747f4c06258213b557cf8edf92c249162 100644
--- a/common/compiler/solidity.go
+++ b/common/compiler/solidity.go
@@ -142,7 +142,6 @@ func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion strin
 	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 {
@@ -151,14 +150,10 @@ func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion strin
 		if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil {
 			return nil, fmt.Errorf("solc: error reading abi definition (%v)", err)
 		}
-		var userdoc interface{}
-		if err := json.Unmarshal([]byte(info.Userdoc), &userdoc); err != nil {
-			return nil, fmt.Errorf("solc: error reading user doc: %v", err)
-		}
-		var devdoc interface{}
-		if err := json.Unmarshal([]byte(info.Devdoc), &devdoc); err != nil {
-			return nil, fmt.Errorf("solc: error reading dev doc: %v", err)
-		}
+		var userdoc, devdoc interface{}
+		json.Unmarshal([]byte(info.Userdoc), &userdoc)
+		json.Unmarshal([]byte(info.Devdoc), &devdoc)
+
 		contracts[name] = &Contract{
 			Code:        "0x" + info.Bin,
 			RuntimeCode: "0x" + info.BinRuntime,