Skip to content

Commit

Permalink
add custom evm-version to abigen (#1768)
Browse files Browse the repository at this point in the history
This was a feature that was needed for #1650 since our version of embedded geth is too old to support push0 (see #1767). It also allows us to target any evm for abigen by passing the param to the solc compiler.

Co-authored-by: Trajan0x <trajan0x@users.noreply.github.com>
  • Loading branch information
trajan0x and trajan0x authored Jan 7, 2024
1 parent 26d1fae commit 859697c
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 11 deletions.
43 changes: 41 additions & 2 deletions tools/abigen/cmd/commands.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package cmd

import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/synapsecns/sanguine/core"
"github.com/synapsecns/sanguine/tools/abigen/internal"
"github.com/urfave/cli/v2"
"os"
)

var solFlag = &cli.StringFlag{
Expand Down Expand Up @@ -31,12 +34,37 @@ var urlFlag = &cli.StringFlag{
Usage: "url of the etherscan api to use",
}

var disableCI = &cli.BoolFlag{
Name: "disable-ci",
Usage: "wether or not to disable regeneration on ci",
}

var disableCIEtherscan = &cli.BoolFlag{
Name: disableCI.Name,
Usage: "wether or not to disable regeneration on ci, this is disabled on etherscan by default because of api keys",
Value: true,
}

var optimizerRunsFlags = &cli.IntFlag{
Name: "optimizer-runs",
Usage: "number of optimizations to run.",
Value: 10000,
}

var evmVersionFlags = &cli.StringFlag{
Name: "evm-version",
Usage: "evm version to target",
}

// strToPt converts a string to a pointer
// crucially, will return nil if stirng is empty
func strToPt(str string) *string {
if str == "" {
return nil
}
return core.PtrTo(str)
}

// GenerateCommand generates abi using flags.
var GenerateCommand = &cli.Command{
Name: "generate",
Expand All @@ -47,10 +75,16 @@ var GenerateCommand = &cli.Command{
filenameFlag,
solVersionFlag,
optimizerRunsFlags,
evmVersionFlags,
disableCI,
},
Action: func(context *cli.Context) error {
if context.Bool(disableCI.Name) && os.Getenv("CI") != "" {
fmt.Print("skipping generation")
return nil
}
//nolint: wrapcheck
return internal.BuildTemplates(context.String(solVersionFlag.Name), context.String(solFlag.Name), context.String(pkgFlag.Name), context.String(filenameFlag.Name), context.Int(optimizerRunsFlags.Name))
return internal.BuildTemplates(context.String(solVersionFlag.Name), context.String(solFlag.Name), context.String(pkgFlag.Name), context.String(filenameFlag.Name), context.Int(optimizerRunsFlags.Name), strToPt(context.String(evmVersionFlags.Name)))
},
}

Expand All @@ -75,10 +109,15 @@ var EtherscanCommand = &cli.Command{
filenameFlag,
solVersionFlag,
urlFlag,
disableCIEtherscan,
},
// TODO this needs to embed optimizations, etc from the real deployed contract.
Action: func(context *cli.Context) error {
if context.Bool(disableCIEtherscan.Name) && os.Getenv("CI") != "" {
fmt.Print("skipping generation")
return nil
}
//nolint: wrapcheck
return internal.GenerateABIFromEtherscan(context.Context, uint32(context.Int(chainIDFlag.Name)), context.String(urlFlag.Name), common.HexToAddress(context.String(addressFlag.Name)), context.String(filenameFlag.String()), context.String(solVersionFlag.Name), context.String(pkgFlag.Name))
return internal.GenerateABIFromEtherscan(context.Context, uint32(context.Int(chainIDFlag.Name)), context.String(urlFlag.Name), common.HexToAddress(context.String(addressFlag.Name)), context.String(filenameFlag.Name), context.String(solVersionFlag.Name), context.String(pkgFlag.Name))
},
}
4 changes: 2 additions & 2 deletions tools/abigen/internal/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ func CreateRunFile(version string) (runFile *os.File, err error) {
}

// CompileSolidity exports compileSolidity for testingw.
func CompileSolidity(version string, filePath string, optimizeRuns int) (map[string]*compiler.Contract, error) {
return compileSolidity(version, filePath, optimizeRuns)
func CompileSolidity(version string, filePath string, optimizeRuns int, evmVersion *string) (map[string]*compiler.Contract, error) {
return compileSolidity(version, filePath, optimizeRuns, evmVersion)
}

// FilePathsAreEqual exports filePathsAreEqual for testing.
Expand Down
15 changes: 10 additions & 5 deletions tools/abigen/internal/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func GenerateABIFromEtherscan(ctx context.Context, chainID uint32, url string, c
return fmt.Errorf("could not get contract source for address %s: %w", contractAddress, err)
}

solFile, err := os.CreateTemp("", fmt.Sprintf("%s.sol", path.Base(fileName)))
solFile, err := os.Create(fmt.Sprintf("%s/%s.sol", os.TempDir(), path.Base(fileName)))
if err != nil {
return fmt.Errorf("could not determine wd: %w", err)
}
Expand All @@ -51,13 +51,13 @@ func GenerateABIFromEtherscan(ctx context.Context, chainID uint32, url string, c
optimizerRuns = contract.Runs
}

return BuildTemplates(solVersion, solFile.Name(), pkgName, fileName, optimizerRuns)
return BuildTemplates(solVersion, solFile.Name(), pkgName, fileName, optimizerRuns, nil)
}

// BuildTemplates builds the templates. version is the solidity version to use and sol is the solidity file to use.
func BuildTemplates(version, file, pkg, filename string, optimizerRuns int) error {
func BuildTemplates(version, file, pkg, filename string, optimizerRuns int, evmVersion *string) error {
// TODO ast
contracts, err := compileSolidity(version, file, optimizerRuns)
contracts, err := compileSolidity(version, file, optimizerRuns, evmVersion)
if err != nil {
return err
}
Expand Down Expand Up @@ -123,7 +123,7 @@ func BuildTemplates(version, file, pkg, filename string, optimizerRuns int) erro

// compileSolidity uses docker to compile solidity.
// nolint: cyclop
func compileSolidity(version string, filePath string, optimizeRuns int) (map[string]*compiler.Contract, error) {
func compileSolidity(version string, filePath string, optimizeRuns int, evmVersion *string) (map[string]*compiler.Contract, error) {
runFile, err := createRunFile(version)
if err != nil {
return nil, err
Expand Down Expand Up @@ -183,6 +183,11 @@ func compileSolidity(version string, filePath string, optimizeRuns int) (map[str
// compile the solidity
var stderr, stdout bytes.Buffer
args := []string{"--combined-json", "bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes", "--optimize", "--optimize-runs", strconv.Itoa(optimizeRuns), "--allow-paths", "., ./, ../"}

if evmVersion != nil {
args = append(args, fmt.Sprintf("--evm-version=%s", *evmVersion))
}

//nolint: gosec
cmd := exec.Command(runFile.Name(), append(args, "--", fmt.Sprintf("/solidity/%s", filepath.Base(solFile.Name())))...)
cmd.Stderr = &stderr
Expand Down
28 changes: 26 additions & 2 deletions tools/abigen/internal/generate_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package internal_test

import (
"encoding/json"
"errors"
"github.com/synapsecns/sanguine/core"
"github.com/synapsecns/sanguine/ethergo/debug"
"os"
"os/exec"
"path/filepath"
Expand All @@ -24,8 +27,8 @@ func TestCreateRunFile(t *testing.T) {
}
}

func (a *AbiSuite) TestCompileSolidity() {
vals, err := internal.CompileSolidity("0.8.4", a.exampleFilePath, 1)
func (a *AbiSuite) TestCompileSolidityImplicitEVM() {
vals, err := internal.CompileSolidity("0.8.4", a.exampleFilePath, 1, nil)
Nil(a.T(), err)

Len(a.T(), vals, 1)
Expand All @@ -35,6 +38,27 @@ func (a *AbiSuite) TestCompileSolidity() {
}
}

func (a *AbiSuite) TestCompileSolidityExplicitEVM() {
// default would be shnghai
const testEvmVersion = "istanbul"
vals, err := internal.CompileSolidity("0.8.20", a.exampleFilePath, 1, core.PtrTo(testEvmVersion))
Nil(a.T(), err)

Len(a.T(), vals, 1)
for _, value := range vals {
Equal(a.T(), value.Info.CompilerVersion, "0.8.20")
Equal(a.T(), value.Info.LanguageVersion, "0.8.20")

var metadata debug.ContractMetadata
err = json.Unmarshal([]byte(value.Info.Metadata), &metadata)
a.Require().NoError(err)

if metadata.Settings.EvmVersion != testEvmVersion {
a.T().Errorf("expected %s to be %s", metadata.Language, testEvmVersion)
}
}
}

func TestFilePathsAreEqual(t *testing.T) {
tests := []struct {
file1 string
Expand Down

0 comments on commit 859697c

Please sign in to comment.