Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions cmd/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"

Expand Down Expand Up @@ -58,7 +57,7 @@ var compileCmd = &cli.Command{
outdir = dir
}

buf, err := ioutil.ReadFile(path)
buf, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("reading solidity: %w", err)
}
Expand All @@ -74,11 +73,11 @@ var compileCmd = &cli.Command{
return fmt.Errorf("prettifying abi: %w", err)
}

if err := ioutil.WriteFile(filepath.Join(outdir, t+".abi"), pretty.Bytes(), 0600); err != nil {
if err := os.WriteFile(filepath.Join(outdir, t+".abi"), pretty.Bytes(), 0600); err != nil {
return fmt.Errorf("writing abi: %w", err)
}

if err := ioutil.WriteFile(filepath.Join(outdir, t+".bin"), []byte(md.Bins[i]), 0600); err != nil {
if err := os.WriteFile(filepath.Join(outdir, t+".bin"), []byte(md.Bins[i]), 0600); err != nil {
return fmt.Errorf("writing bin: %w", err)
}
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cmd

import (
"fmt"
"io/ioutil"
"io"
"log"
"os"

Expand All @@ -19,7 +19,7 @@ func Execute() {
if context.Bool("verbose") {
log.SetFlags(0)
} else {
log.SetOutput(ioutil.Discard)
log.SetOutput(io.Discard)
}
return nil
}
Expand Down
9 changes: 4 additions & 5 deletions codegen/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package codegen
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -59,12 +58,12 @@ func GenerateBindings(path string, outdir string, config *BindingsConfig) error
outdir = dir
}

abi, err := ioutil.ReadFile(path)
abi, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("reading abi: %w", err)
}

bin, err := ioutil.ReadFile(filepath.Join(dir, typ+".bin"))
bin, err := os.ReadFile(filepath.Join(dir, typ+".bin"))
if errors.Is(err, os.ErrNotExist) {
bin = []byte{}
} else if err != nil {
Expand All @@ -85,7 +84,7 @@ func GenerateBindings(path string, outdir string, config *BindingsConfig) error
return fmt.Errorf("generating handler: %w", err)
}

if err := ioutil.WriteFile(filepath.Join(outdir, name+".handlers.go"), []byte(handler), 0600); err != nil {
if err := os.WriteFile(filepath.Join(outdir, name+".handlers.go"), []byte(handler), 0600); err != nil {
return fmt.Errorf("writing handler: %w", err)
}
}
Expand All @@ -112,7 +111,7 @@ func GenerateBindings(path string, outdir string, config *BindingsConfig) error
return fmt.Errorf("binding abi: %w", err)
}

if err := ioutil.WriteFile(filepath.Join(outdir, name+".go"), []byte(src), 0600); err != nil {
if err := os.WriteFile(filepath.Join(outdir, name+".go"), []byte(src), 0600); err != nil {
return fmt.Errorf("writing ABI binding: %w", err)
}
}
Expand Down
68 changes: 68 additions & 0 deletions compiler/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Removed from go-ethereum in v1.10.18
// Original: https://github.com/ethereum/go-ethereum/blob/v1.10.17/common/compiler/helpers.go

// Copyright 2019 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 <http://www.gnu.org/licenses/>.

// Package compiler wraps the Solidity and Vyper compiler executables (solc; vyper).
package compiler

import (
"bytes"
"os"
"regexp"
)

var versionRegexp = regexp.MustCompile(`([0-9]+)\.([0-9]+)\.([0-9]+)`)

// Contract contains information about a compiled contract, alongside its code and runtime code.
type Contract struct {
Code string `json:"code"`
RuntimeCode string `json:"runtime-code"`
Info ContractInfo `json:"info"`
Hashes map[string]string `json:"hashes"`
}

// ContractInfo contains information about a compiled contract, including access
// to the ABI definition, source mapping, user and developer docs, and metadata.
//
// Depending on the source, language version, compiler version, and compiler
// options will provide information about how the contract was compiled.
type ContractInfo struct {
Source string `json:"source"`
Language string `json:"language"`
LanguageVersion string `json:"languageVersion"`
CompilerVersion string `json:"compilerVersion"`
CompilerOptions string `json:"compilerOptions"`
SrcMap interface{} `json:"srcMap"`
SrcMapRuntime string `json:"srcMapRuntime"`
AbiDefinition interface{} `json:"abiDefinition"`
UserDoc interface{} `json:"userDoc"`
DeveloperDoc interface{} `json:"developerDoc"`
Metadata string `json:"metadata"`
}

func slurpFiles(files []string) (string, error) {
var concat bytes.Buffer
for _, file := range files {
content, err := os.ReadFile(file)
if err != nil {
return "", err
}
concat.Write(content)
}
return concat.String(), nil
}
231 changes: 231 additions & 0 deletions compiler/solidity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
// Removed from go-ethereum in v1.10.18
//
// DIFF https://github.com/ethereum/go-ethereum/commit/8541ddbd951370b2a42df8d82b0633ff0efeba12#diff-04450f168c213550a12facbbf272c9a55fb4638cab4bd7a3601c47b1e1ebcfba
//
// Original file
// https://github.com/ethereum/go-ethereum/blob/v1.10.17/common/compiler/solidity.go

// Copyright 2015 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 <http://www.gnu.org/licenses/>.

// Package compiler wraps the Solidity and Vyper compiler executables (solc; vyper).
package compiler

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"os/exec"
"strconv"
"strings"
)

// Solidity contains information about the solidity compiler.
type Solidity struct {
Path, Version, FullVersion string
Major, Minor, Patch int
}

// --combined-output format
type solcOutput struct {
Contracts map[string]struct {
BinRuntime string `json:"bin-runtime"`
SrcMapRuntime string `json:"srcmap-runtime"`
Bin, SrcMap, Abi, Devdoc, Userdoc, Metadata string
Hashes map[string]string
}
Version string
}

// solidity v.0.8 changes the way ABI, Devdoc and Userdoc are serialized
type solcOutputV8 struct {
Contracts map[string]struct {
BinRuntime string `json:"bin-runtime"`
SrcMapRuntime string `json:"srcmap-runtime"`
Bin, SrcMap, Metadata string
Abi interface{}
Devdoc interface{}
Userdoc interface{}
Hashes map[string]string
}
Version string
}

func (s *Solidity) makeArgs() []string {
p := []string{
"--combined-json", "bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc",
"--optimize", // code optimizer switched on
"--allow-paths", "., ./, ../", // default to support relative paths
}
if s.Major > 0 || s.Minor > 4 || s.Patch > 6 {
p[1] += ",metadata,hashes"
}
return p
}

// SolidityVersion runs solc and parses its version output.
func SolidityVersion(solc string) (*Solidity, error) {
if solc == "" {
solc = "solc"
}
var out bytes.Buffer
cmd := exec.Command(solc, "--version")
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return nil, err
}
matches := versionRegexp.FindStringSubmatch(out.String())
if len(matches) != 4 {
return nil, fmt.Errorf("can't parse solc version %q", out.String())
}
s := &Solidity{Path: cmd.Path, FullVersion: out.String(), Version: matches[0]}
if s.Major, err = strconv.Atoi(matches[1]); err != nil {
return nil, err
}
if s.Minor, err = strconv.Atoi(matches[2]); err != nil {
return nil, err
}
if s.Patch, err = strconv.Atoi(matches[3]); err != nil {
return nil, err
}
return s, nil
}

// CompileSolidityString builds and returns all the contracts contained within a source string.
func CompileSolidityString(solc, source string) (map[string]*Contract, error) {
if len(source) == 0 {
return nil, errors.New("solc: empty source string")
}
s, err := SolidityVersion(solc)
if err != nil {
return nil, err
}
args := append(s.makeArgs(), "--")
cmd := exec.Command(s.Path, append(args, "-")...)
cmd.Stdin = strings.NewReader(source)
return s.run(cmd, source)
}

// CompileSolidity compiles all given Solidity source files.
func CompileSolidity(solc string, sourcefiles ...string) (map[string]*Contract, error) {
if len(sourcefiles) == 0 {
return nil, errors.New("solc: no source files")
}
source, err := slurpFiles(sourcefiles)
if err != nil {
return nil, err
}
s, err := SolidityVersion(solc)
if err != nil {
return nil, err
}
args := append(s.makeArgs(), "--")
cmd := exec.Command(s.Path, append(args, sourcefiles...)...)
return s.run(cmd, source)
}

func (s *Solidity) run(cmd *exec.Cmd, source string) (map[string]*Contract, error) {
var stderr, stdout bytes.Buffer
cmd.Stderr = &stderr
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("solc: %v\n%s", err, stderr.Bytes())
}
return ParseCombinedJSON(stdout.Bytes(), source, s.Version, s.Version, strings.Join(s.makeArgs(), " "))
}

// ParseCombinedJSON takes the direct output of a solc --combined-output run and
// parses it into a map of string contract name to Contract structs. The
// provided source, language and compiler version, and compiler options are all
// passed through into the Contract structs.
//
// The solc output is expected to contain ABI, source mapping, user docs, and dev docs.
//
// Returns an error if the JSON is malformed or missing data, or if the JSON
// embedded within the JSON is malformed.
func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) {
var output solcOutput
if err := json.Unmarshal(combinedJSON, &output); err != nil {
// Try to parse the output with the new solidity v.0.8.0 rules
return parseCombinedJSONV8(combinedJSON, source, languageVersion, compilerVersion, compilerOptions)
}
// Compilation succeeded, assemble and return the contracts.
contracts := make(map[string]*Contract)
for name, info := range output.Contracts {
// Parse the individual compilation results.
var abi interface{}
if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil {
return nil, fmt.Errorf("solc: error reading abi definition (%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,
Hashes: info.Hashes,
Info: ContractInfo{
Source: source,
Language: "Solidity",
LanguageVersion: languageVersion,
CompilerVersion: compilerVersion,
CompilerOptions: compilerOptions,
SrcMap: info.SrcMap,
SrcMapRuntime: info.SrcMapRuntime,
AbiDefinition: abi,
UserDoc: userdoc,
DeveloperDoc: devdoc,
Metadata: info.Metadata,
},
}
}
return contracts, nil
}

// parseCombinedJSONV8 parses the direct output of solc --combined-output
// and parses it using the rules from solidity v.0.8.0 and later.
func parseCombinedJSONV8(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) {
var output solcOutputV8
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 {
contracts[name] = &Contract{
Code: "0x" + info.Bin,
RuntimeCode: "0x" + info.BinRuntime,
Hashes: info.Hashes,
Info: ContractInfo{
Source: source,
Language: "Solidity",
LanguageVersion: languageVersion,
CompilerVersion: compilerVersion,
CompilerOptions: compilerOptions,
SrcMap: info.SrcMap,
SrcMapRuntime: info.SrcMapRuntime,
AbiDefinition: info.Abi,
UserDoc: info.Userdoc,
DeveloperDoc: info.Devdoc,
Metadata: info.Metadata,
},
}
}
return contracts, nil
}
Loading