diff --git a/gethwrappers/generation/generate/genwrapper/genwrapper.go b/gethwrappers/generation/generate/genwrapper/genwrapper.go index 2229645a09..0ffe3142d1 100644 --- a/gethwrappers/generation/generate/genwrapper/genwrapper.go +++ b/gethwrappers/generation/generate/genwrapper/genwrapper.go @@ -32,7 +32,7 @@ func GenWrapper(abiPath, binPath, className, pkgName, outDirSuffixInput string) gethwrappers.Exit("could not get working directory", err) } outDir := filepath.Join(cwd, "generated", outDirSuffixInput, pkgName) - if mkdErr := os.MkdirAll(outDir, 0700); err != nil { + if mkdErr := os.MkdirAll(outDir, 0700); mkdErr != nil { gethwrappers.Exit( fmt.Sprintf("failed to create wrapper dir, outDirSuffixInput: %s (could be empty)", outDirSuffixInput), mkdErr) diff --git a/gethwrappers/helpers/abigen.go b/gethwrappers/helpers/abigen.go index 64234420f2..b1ced15636 100644 --- a/gethwrappers/helpers/abigen.go +++ b/gethwrappers/helpers/abigen.go @@ -10,7 +10,6 @@ import ( "go/token" "os" "os/exec" - "path/filepath" "regexp" "strconv" "strings" @@ -30,7 +29,7 @@ var GethVersion = fmt.Sprintf("%d.%d.%d", version.Major, version.Minor, version. // AbigenArgs is the arguments to the abigen executable. E.g., Bin is the -bin arg. // Metadata is the only exception, as it is not passed to abigen but rather used to create a separate metadata variable. type AbigenArgs struct { - Bin, ABI, BuildInfo, Metadata, Out, BuildInfoOut, Type, Pkg string + Bin, ABI, BuildInfo, Metadata, Out, BuildInfoOut, Type, Pkg, AbiGenPath string } // compiler defines the compiler section of contract metadata. @@ -67,12 +66,10 @@ func Abigen(a AbigenArgs) { includeMetadata := os.Getenv("metadata") == "true" var versionResponse bytes.Buffer - abigenExecutablePath := filepath.Join(GetProjectRoot(), "../../../tools/bin/abigen") - abigenVersionCheck := exec.Command(abigenExecutablePath, "--version") + abigenVersionCheck := exec.Command(a.AbiGenPath, "--version") abigenVersionCheck.Stdout = &versionResponse if err := abigenVersionCheck.Run(); err != nil { - Exit("no native abigen; you must install it (`make abigen` in the "+ - "chainlink root dir)", err) + Exit("no native abigen; you must install it (`make abigen` in the chainlink root dir)", err) } version := string(regexp.MustCompile(`[0-9]+\.[0-9]+\.[0-9]+`).Find( versionResponse.Bytes())) @@ -89,7 +86,7 @@ func Abigen(a AbigenArgs) { if a.Bin != "-" { args = append(args, "-bin", a.Bin) } - buildCommand := exec.Command(abigenExecutablePath, args...) + buildCommand := exec.Command(a.AbiGenPath, args...) var buildResponse bytes.Buffer buildCommand.Stderr = &buildResponse if err := buildCommand.Run(); err != nil { @@ -110,13 +107,13 @@ func genMetadata(abigenArgs AbigenArgs) { Exit("Error while reading build info file", err) } // Unmarshal into BuildInfo struct to filter out unnecessary fields - // and marshal back to JSON bytes afterwards + // and marshal back to JSON bytes afterward var build buildInfo err = json.Unmarshal(info, &build) if err != nil { Exit("Error while unmarshalling build info JSON", err) } - // Get version from metadata file, as it contains the commit hash required by etherscan + // Get version from metadata file, as it contains the commit hash required by Etherscan metadataBytes, err := os.ReadFile(abigenArgs.Metadata) if err != nil { Exit("Error while reading metadata file", err) diff --git a/gethwrappers/helpers/extract_bytecode/main.go b/gethwrappers/helpers/extract_bytecode/main.go index b6c399aeb9..a12278a8d2 100644 --- a/gethwrappers/helpers/extract_bytecode/main.go +++ b/gethwrappers/helpers/extract_bytecode/main.go @@ -42,8 +42,11 @@ func run() error { } // Validate input directory exists - if _, err := os.Stat(*inputDir); os.IsNotExist(err) { - return fmt.Errorf("input directory does not exist: %s", *inputDir) + if _, err := os.Stat(*inputDir); err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("input directory does not exist: %s", *inputDir) + } + return fmt.Errorf("failed to stat input directory %s: %w", *inputDir, err) } fmt.Printf("Input dir: %s\n", *inputDir) diff --git a/gethwrappers/helpers/generate/wrap.go b/gethwrappers/helpers/generate/wrap.go index 1d78c5ea9a..6c30732366 100644 --- a/gethwrappers/helpers/generate/wrap.go +++ b/gethwrappers/helpers/generate/wrap.go @@ -1,107 +1,27 @@ package main import ( - "fmt" "os" "path/filepath" - gethwrappers "github.com/smartcontractkit/chainlink-evm/gethwrappers/helpers" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/helpers/generate/wrap" zksyncwrapper "github.com/smartcontractkit/chainlink-evm/gethwrappers/helpers/zksync" ) -var ( - rootDir = "../../solc/" -) - func main() { - project := os.Args[1] - className := os.Args[2] - pkgName := os.Args[3] + solcProjectRoot := os.Args[1] + abiGenPath := os.Args[2] + contract := os.Args[3] + pkgName := os.Args[4] - var outDirSuffix string - if len(os.Args) >= 5 { - outDirSuffix = os.Args[4] - } else { - outDirSuffix = "latest" - } + outDirSuffix := "latest" if os.Getenv("ZKSYNC") == "true" { - outDir := getOutDir(outDirSuffix, pkgName) - zksyncBytecodePath := filepath.Join("..", "zkout", className+".sol", className+".json") + zksyncBytecodePath := filepath.Join("..", "zkout", contract+".sol", contract+".json") zksyncBytecode := zksyncwrapper.ReadBytecodeFromForgeJSON(zksyncBytecodePath) - outPath := filepath.Join(outDir, pkgName+"_zksync.go") - zksyncwrapper.WrapZksyncDeploy(zksyncBytecode, className, pkgName, outPath) + outPath := filepath.Join(wrap.GetOutDir(outDirSuffix, pkgName), pkgName+"_zksync.go") + zksyncwrapper.WrapZksyncDeploy(zksyncBytecode, contract, pkgName, outPath) } else { - abiPath := rootDir + project + "/" + className + "/" + className + ".sol/" + className + ".abi.json" - metadataPath := rootDir + project + "/" + className + "/" + className + ".sol/" + className + ".metadata.json" - binPath := rootDir + project + "/" + className + "/" + className + ".sol/" + className + ".bin" - buildInfoPath := rootDir + project + "/" + className + "/build/build.json" - - GenWrapper(abiPath, binPath, buildInfoPath, metadataPath, className, pkgName, outDirSuffix) - } -} - -// GenWrapper generates a contract wrapper for the given contract. -// -// abiPath is the path to the contract's ABI JSON file. -// -// binPath is the path to the contract's binary file, typically with .bin extension. -// -// className is the name of the generated contract class. -// -// pkgName is the name of the package the contract will be generated in. Try -// to follow idiomatic Go package naming conventions where possible. -// -// outDirSuffixInput is the directory suffix to generate the wrapper in. If not provided, the -// wrapper will be generated in the default location. The default location is -// /generated//.go. The suffix will take place after -// the /generated, so the overridden location would be -// /generated///.go. -func GenWrapper(abiPath, binPath, buildInfoPath, metadataPath, className, pkgName, outDirSuffixInput string) { - fmt.Println("Generating", pkgName, "contract wrapper") - - outDir := getOutDir(outDirSuffixInput, pkgName) - outPath := filepath.Join(outDir, pkgName+".go") - metadataOutPath := filepath.Join(outDir, pkgName+"_metadata.go") - - gethwrappers.Abigen(gethwrappers.AbigenArgs{ - Bin: binPath, - ABI: abiPath, - BuildInfo: buildInfoPath, - Metadata: metadataPath, - Out: outPath, - BuildInfoOut: metadataOutPath, - Type: className, - Pkg: pkgName, - }) - - // Build succeeded, so update the versions db with the new contract data - versions, err := gethwrappers.ReadVersionsDB() - if err != nil { - gethwrappers.Exit("could not read current versions database", err) - } - versions.GethVersion = gethwrappers.GethVersion - versions.ContractVersions[pkgName] = gethwrappers.ContractVersion{ - Hash: gethwrappers.VersionHash(abiPath, binPath), - AbiPath: abiPath, - BinaryPath: binPath, + wrap.GenWrapper(solcProjectRoot, contract, pkgName, outDirSuffix, abiGenPath) } - if err := gethwrappers.WriteVersionsDB(versions); err != nil { - gethwrappers.Exit("could not save versions db", err) - } -} - -func getOutDir(outDirSuffixInput, pkgName string) string { - cwd, err := os.Getwd() // gethwrappers directory - if err != nil { - gethwrappers.Exit("could not get working directory", err) - } - outDir := filepath.Join(cwd, "generated", outDirSuffixInput, pkgName) - if mkdErr := os.MkdirAll(outDir, 0700); err != nil { - gethwrappers.Exit( - fmt.Sprintf("failed to create wrapper dir, outDirSuffixInput: %s (could be empty)", outDirSuffixInput), - mkdErr) - } - - return outDir } diff --git a/gethwrappers/helpers/generate/wrap/wrap.go b/gethwrappers/helpers/generate/wrap/wrap.go new file mode 100644 index 0000000000..10d96d4c1e --- /dev/null +++ b/gethwrappers/helpers/generate/wrap/wrap.go @@ -0,0 +1,78 @@ +package wrap + +import ( + "fmt" + "os" + "path/filepath" + + gethwrappers "github.com/smartcontractkit/chainlink-evm/gethwrappers/helpers" +) + +// GenWrapper generates a contract wrapper for the given contract. +// +// solcProjectRoot is the path to the solc artifacts for the project, e.g. `"../../contracts/solc/" + project` +// abiPath is the path to the contract's ABI JSON file. +// binPath is the path to the contract's binary file, typically with .bin extension. +// contract is the name of the generated contract class. +// pkgName is the name of the package the contract will be generated in. Try +// to follow idiomatic Go package naming conventions where possible. +// +// outDirSuffixInput is the directory suffix to generate the wrapper in. If not provided, the +// wrapper will be generated in the default location. The default location is +// /generated//.go. The suffix will take place after +// the /generated, so the overridden location would be +// /generated///.go. +func GenWrapper(solcProjectRoot, contract, pkgName, outDirSuffixInput, abiGenPath string) { + abiPath := filepath.Join(solcProjectRoot, contract, contract+".sol", contract+".abi.json") + metadataPath := filepath.Join(solcProjectRoot, contract, contract+".sol", contract+".metadata.json") + binPath := filepath.Join(solcProjectRoot, contract, contract+".sol", contract+".bin") + buildInfoPath := filepath.Join(solcProjectRoot, contract, "build", "build.json") + + fmt.Println("Generating", pkgName, "contract wrapper") + + outDir := GetOutDir(outDirSuffixInput, pkgName) + outPath := filepath.Join(outDir, pkgName+".go") + metadataOutPath := filepath.Join(outDir, pkgName+"_metadata.go") + + gethwrappers.Abigen(gethwrappers.AbigenArgs{ + Bin: binPath, + ABI: abiPath, + BuildInfo: buildInfoPath, + Metadata: metadataPath, + Out: outPath, + BuildInfoOut: metadataOutPath, + Type: contract, + Pkg: pkgName, + AbiGenPath: abiGenPath, + }) + + // Build succeeded, so update the versions db with the new contract data + versions, err := gethwrappers.ReadVersionsDB() + if err != nil { + gethwrappers.Exit("could not read current versions database", err) + } + versions.GethVersion = gethwrappers.GethVersion + versions.ContractVersions[pkgName] = gethwrappers.ContractVersion{ + Hash: gethwrappers.VersionHash(abiPath, binPath), + AbiPath: abiPath, + BinaryPath: binPath, + } + if err := gethwrappers.WriteVersionsDB(versions); err != nil { + gethwrappers.Exit("could not save versions db", err) + } +} + +func GetOutDir(outDirSuffixInput, pkgName string) string { + cwd, err := os.Getwd() // gethwrappers directory + if err != nil { + gethwrappers.Exit("could not get working directory", err) + } + outDir := filepath.Join(cwd, "generated", outDirSuffixInput, pkgName) + if mkdErr := os.MkdirAll(outDir, 0700); mkdErr != nil { + gethwrappers.Exit( + fmt.Sprintf("failed to create wrapper dir, outDirSuffixInput: %s (could be empty)", outDirSuffixInput), + mkdErr) + } + + return outDir +} diff --git a/gethwrappers/helpers/utils.go b/gethwrappers/helpers/utils.go index fbb2e40636..1c6f2f1d3d 100644 --- a/gethwrappers/helpers/utils.go +++ b/gethwrappers/helpers/utils.go @@ -4,7 +4,6 @@ import ( "crypto/sha256" "fmt" "os" - "path/filepath" ) // VersionHash is the hash used to detect changes in the underlying contract @@ -17,7 +16,7 @@ func VersionHash(abiPath string, binPath string) (hash string) { if binPath != "-" { bin, err = os.ReadFile(binPath) if err != nil { - Exit("Could not read abi path to create version hash", err) + Exit("Could not read bin path to create version hash", err) } } hashMsg := string(abi) + string(bin) + "\n" @@ -32,20 +31,3 @@ func Exit(msg string, err error) { } os.Exit(1) } - -// GetProjectRoot returns the root of the chainlink project -func GetProjectRoot() (rootPath string) { - root, err := os.Getwd() - if err != nil { - Exit("could not get current working directory while seeking project root", - err) - } - for root != "/" { // Walk up path to find dir containing go.mod - if _, err := os.Stat(filepath.Join(root, "go.mod")); !os.IsNotExist(err) { - return root - } - root = filepath.Dir(root) - } - Exit("could not find project root", nil) - panic("can't get here") -}