1

I have a file that is composed of 5 imports, too much code to drop here so I will illustrate my question with a very simplified example. My Test.sol file:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

contract Cat{
    uint private x;
    constructor(){}
    function myFunction() external{
        x = 3;
    }
}

contract Kitten is Cat{
    constructor(){}
}

Here is the file structure:

$ tree
.
├── api
│   └── Kitten.go
├── go.mod
├── go.sum
├── main.go
├── solc-output
│   ├── Cat.abi
│   ├── Cat.bin
│   ├── Kitten.abi
│   └── Kitten.bin
└── Test.sol

The go file:

package main

import (
    "fmt"
    "log"
    "os"
    "os/exec"
    "path/filepath"
)

func main() {
    // Define paths
    contractFile := "./Test.sol" // Path to the Solidity contract
    outputDir := "./solc-output" // Directory to store ABI and BIN files
    apiDir := "./api"            // Directory to store generated Go bindings

    // Ensure output and API directories exist
    os.MkdirAll(outputDir, os.ModePerm) //nolint:errcheck
    os.MkdirAll(apiDir, os.ModePerm)    //nolint:errcheck

    // Compile the contract using solc
    cmd := exec.Command("solc", "--optimize", "--abi", "--bin", "--overwrite", "--output-dir", outputDir, contractFile)
    output, err := cmd.CombinedOutput()
    if err != nil {
        log.Fatalf("Failed to compile contract: %v\nOutput: %s", err, string(output))
    }
    fmt.Println("Contract compiled successfully")

    // Generate Go bindings using abigen
    abiFile := filepath.Join(outputDir, "Kitten.abi")
    binFile := filepath.Join(outputDir, "Kitten.bin")
    outFile := filepath.Join(apiDir, "Kitten.go")

    cmd = exec.Command("abigen", "--bin="+binFile, "--abi="+abiFile, "--pkg=Kitten", "--type=Kitten", "--out="+outFile) //nolint:gosec
    output, err = cmd.CombinedOutput()
    if err != nil {
        log.Fatalf("Failed to generate Go bindings: %v\nOutput: %s", err, string(output))
    }
    fmt.Println("Go bindings generated successfully")
}

And finally my compilers:

$ abigen --version
abigen version 1.11.7-unstable-d3ece3a0-20230421
$ solc --version
solc, the solidity compiler commandline interface
Version: 0.8.25+commit.b61c2a91.Linux.g++

This is my problem. I was under the impression that the flattened file will be compiled by solc into one Kitten.bin and one Kitten.abi. I got two kinds, Kitten and Cat files. These files are now used as arguments to abigen.
But in my code I am only using the Kitten files, the functionality of Cat does not seem to be included given the separation of Kitten and Cat files.

How can I use both Kitten and Cat files as argument to abigen or generate one bin file and one bin file to use as argument?

Any input on this would be highly appreciated.

------------------New Comments Below------------------
I made some adjustments and posted the code on Gitub then I deployed and verified the Solidity contract on Sepolia. I compared the generated abi and bin files between the code base on Github and the code generated by Etherscan. The abi and bin files differ greatly. I would expect to get two identical files: Github.Abi == Sepolia.Abi && Github.Bin == Sepolia.Bin

But that is not the case.

Any ideas?

1 Answer 1

1

One approach to achieve this is to concatenate the ABI and BIN files of both contracts before passing them to abigen.

You can do this by reading the contents of the separate ABI and BIN files for Cat and Kitten contracts, and then merging them into one ABI file and one BIN file. Finally, you can use these merged files as arguments to abigen.

Here’s a simplified version of how you could modify your code:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "os/exec"
    "path/filepath"
)

func main() {
    // Define paths
    outputDir := "./solc-output" // Directory to store ABI and BIN files
    apiDir := "./api"            // Directory to store generated Go bindings

    // Ensure API directory exists
    os.MkdirAll(apiDir, os.ModePerm) //nolint:errcheck

    // Read ABI and BIN files for Cat and Kitten
    catABI, _ := ioutil.ReadFile(filepath.Join(outputDir, "Cat.abi"))
    catBIN, _ := ioutil.ReadFile(filepath.Join(outputDir, "Cat.bin"))
    kittenABI, _ := ioutil.ReadFile(filepath.Join(outputDir, "Kitten.abi"))
    kittenBIN, _ := ioutil.ReadFile(filepath.Join(outputDir, "Kitten.bin"))

    // Concatenate ABI and BIN files
    mergedABI := append(catABI, kittenABI...)
    mergedBIN := append(catBIN, kittenBIN...)

    // Write merged ABI and BIN files
    mergedABIFilename := filepath.Join(outputDir, "Merged.abi")
    mergedBINFilename := filepath.Join(outputDir, "Merged.bin")
    _ = ioutil.WriteFile(mergedABIFilename, mergedABI, 0644)
    _ = ioutil.WriteFile(mergedBINFilename, mergedBIN, 0644)

    // Generate Go bindings using abigen
    outFile := filepath.Join(apiDir, "Kitten.go")

    cmd := exec.Command("abigen", "--bin="+mergedBINFilename, "--abi="+mergedABIFilename, "--pkg=Kitten", "--type=Kitten", "--out="+outFile) //nolint:gosec
    output, err := cmd.CombinedOutput()
    if err != nil {
        log.Fatalf("Failed to generate Go bindings: %v\nOutput: %s", err, string(output))
    }
    fmt.Println("Go bindings generated successfully")
}

P.S., Make sure to adjust the file paths and error handling as needed for your specific use case.

1
  • Please see initial issue above: ------------------New Comments Below------------------
    – pigfox
    Commented Apr 29 at 3:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.