// Copyright 2024 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 bind_test import ( "encoding/json" "os" "path/filepath" "strings" "testing" "github.com/ethereum/go-ethereum/accounts/abi/abigen" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common/compiler" "github.com/ethereum/go-ethereum/crypto" ) // Run go generate to recreate the test bindings. // //go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/db/combined-abi.json -type DBStats -pkg db -out internal/contracts/db/bindings.go //go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/events/combined-abi.json -type C -pkg events -out internal/contracts/events/bindings.go //go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/nested_libraries/combined-abi.json -type C1 -pkg nested_libraries -out internal/contracts/nested_libraries/bindings.go //go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/solc_errors/combined-abi.json -type C -pkg solc_errors -out internal/contracts/solc_errors/bindings.go //go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/uint256arrayreturn/combined-abi.json -type C -pkg uint256arrayreturn -out internal/contracts/uint256arrayreturn/bindings.go // TestBindingGeneration tests that re-running generation of bindings does not result in // mutations to the binding code. func TestBindingGeneration(t *testing.T) { matches, _ := filepath.Glob("internal/contracts/*") var dirs []string for _, match := range matches { f, _ := os.Stat(match) if f.IsDir() { dirs = append(dirs, f.Name()) } } for _, dir := range dirs { var ( abis []string bins []string types []string libs = make(map[string]string) ) basePath := filepath.Join("internal/contracts", dir) combinedJsonPath := filepath.Join(basePath, "combined-abi.json") abiBytes, err := os.ReadFile(combinedJsonPath) if err != nil { t.Fatalf("error trying to read file %s: %v", combinedJsonPath, err) } contracts, err := compiler.ParseCombinedJSON(abiBytes, "", "", "", "") if err != nil { t.Fatalf("Failed to read contract information from json output: %v", err) } for name, contract := range contracts { // fully qualified name is of the form : nameParts := strings.Split(name, ":") typeName := nameParts[len(nameParts)-1] abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse if err != nil { utils.Fatalf("Failed to parse ABIs from compiler output: %v", err) } abis = append(abis, string(abi)) bins = append(bins, contract.Code) types = append(types, typeName) // Derive the library placeholder which is a 34 character prefix of the // hex encoding of the keccak256 hash of the fully qualified library name. // Note that the fully qualified library name is the path of its source // file and the library name separated by ":". libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] // the first 2 chars are 0x libs[libPattern] = typeName } code, err := abigen.BindV2(types, abis, bins, dir, libs, make(map[string]string)) if err != nil { t.Fatalf("error creating bindings for package %s: %v", dir, err) } existingBindings, err := os.ReadFile(filepath.Join(basePath, "bindings.go")) if err != nil { t.Fatalf("ReadFile returned error: %v", err) } if code != string(existingBindings) { t.Fatalf("code mismatch for %s", dir) } } }