Skip to content

Commit

Permalink
Print rpc data field in error, format source code, etc
Browse files Browse the repository at this point in the history
  • Loading branch information
10gic committed Mar 4, 2023
1 parent e1c25c2 commit 4693d7b
Show file tree
Hide file tree
Showing 7 changed files with 867 additions and 93 deletions.
61 changes: 61 additions & 0 deletions cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"math/big"
Expand Down Expand Up @@ -38,6 +39,22 @@ func contains(arr []string, str string) bool {
// checkErr panic if err != nil.
func checkErr(err error) {
if err != nil {
if rpcErr, ok := err.(rpc.DataError); ok {
var errData = rpcErr.ErrorData()
log.Printf("data field in error: %v", errData)
if errData != nil {
if errStr, ok := errData.(string); ok && len(errStr) >= 10 {
var funcHash = errStr[0:10]
funcSig, err := getFuncSig(funcHash)
if err != nil {
log.Printf("getFuncSig failed %v", err)
}
for _, data := range funcSig {
log.Printf("%s is signature of %s", funcHash, data)
}
}
}
}
log.Fatalf("%v", err)
// panic(err)
}
Expand Down Expand Up @@ -440,3 +457,47 @@ func RecoverPubkey(v, r, s *big.Int, msg []byte) ([]byte, error) {
// crypto.Ecrecover return 65 bytes uncompressed public key
return crypto.Ecrecover(msg, signature)
}

// getFuncSig recover function signature from 4 bytes hash
// For example:
// param: "0x8c905368"
// return: ["NotEnoughFunds(uint256,uint256)"]
//
// This function uses openchain API
// $ curl -X 'GET' 'https://api.openchain.xyz/signature-database/v1/lookup?function=0x8c905368&filter=true'
// {"ok":true,"result":{"event":{},"function":{"0x8c905368":[{"name":"NotEnoughFunds(uint256,uint256)","filtered":false}]}}}
// See https://openchain.xyz/signatures
func getFuncSig(funcHash string) ([]string, error) {
var url = fmt.Sprintf("https://api.openchain.xyz/signature-database/v1/lookup?function=%s&filter=true", funcHash)
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

type funcSig struct {
Name string `json:"name"`
Filtered bool `json:"filtered"`
}
type respMsg struct {
Ok bool `json:"ok"`
Result struct {
Function map[string][]funcSig `json:"function"`
} `json:"result"`
}
var data respMsg
if err := json.Unmarshal(body, &data); err != nil {
return nil, err
}

var rc []string
for _, data := range data.Result.Function[funcHash] {
rc = append(rc, data.Name)
}

return rc, nil
}
2 changes: 1 addition & 1 deletion cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func findContractName(deploySrcFile string) string {
return ""
}

lastContract := matches[len(matches) - 1]
lastContract := matches[len(matches)-1]
re = regexp.MustCompile(`^[ ]*contract[ ]+(?P<Name>[a-zA-Z0-9_]+) `)
matches = re.FindStringSubmatch(lastContract)
nameIndex := re.SubexpIndex("Name")
Expand Down
19 changes: 10 additions & 9 deletions cmd/downloadsrc.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func init() {
var downloadSrcCmd = &cobra.Command{
Use: "download-src [flags] contract-address",
Short: "Download source code of contract from block explorer platform, eg. etherscan.",
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
// if no file specified, read from stdin
Expand Down Expand Up @@ -50,12 +51,12 @@ func downloadSrc(contractAddress string) error {
}

type respMsg struct {
Status string `json:"status"`
Message string `json:"message"`
Result []struct{
SourceCode string `json:"SourceCode"`
Status string `json:"status"`
Message string `json:"message"`
Result []struct {
SourceCode string `json:"SourceCode"`
ContractName string `json:"ContractName"`
} `json:"result"`
} `json:"result"`
}

var data respMsg
Expand Down Expand Up @@ -86,8 +87,8 @@ func downloadSrc(contractAddress string) error {
Content string `json:"content"`
}
type sourceJson struct {
Language string `json:"language"`
Sources map[string]*SourcesInfo `json:"sources"`
Language string `json:"language"`
Sources map[string]*SourcesInfo `json:"sources"`
}

var data sourceJson
Expand All @@ -113,7 +114,7 @@ func downloadSrc(contractAddress string) error {
// An example: https://api.etherscan.io/api?module=contract&action=getsourcecode&address=0x35036A4b7b012331f23F2945C08A5274CED38AC2

type sourceJson struct {
X map[string]struct{
X map[string]struct {
Content string `json:"content"`
} `json:"-"` // Rest of the fields should go here.
// See https://stackoverflow.com/questions/33436730/unmarshal-json-with-some-known-and-some-unknown-field-names
Expand All @@ -130,7 +131,7 @@ func downloadSrc(contractAddress string) error {
} else {
// Solidity Single file
// An example: https://api.etherscan.io/api?module=contract&action=getsourcecode&address=0xdac17f958d2ee523a2206206994597c13d831ec7
saveContract(filepath.Join(downloadSrcCmdSaveDir, data.Result[0].ContractName + ".sol"), sourceCode)
saveContract(filepath.Join(downloadSrcCmdSaveDir, data.Result[0].ContractName+".sol"), sourceCode)
}

return nil
Expand Down
74 changes: 38 additions & 36 deletions cmd/encodeparam.go
Original file line number Diff line number Diff line change
Expand Up @@ -775,42 +775,44 @@ func typeNormalize(input string) string {

// ABI example:
// [
// {
// "inputs": [],
// "stateMutability": "nonpayable",
// "type": "constructor"
// },
// {
// "inputs": [
// {
// "internalType": "uint256[]",
// "name": "_a",
// "type": "uint256[]"
// },
// {
// "internalType": "address[]",
// "name": "_addr",
// "type": "address[]"
// }
// ],
// "name": "f1",
// "outputs": [],
// "stateMutability": "nonpayable",
// "type": "function"
// },
// {
// "inputs": [],
// "name": "f2",
// "outputs": [
// {
// "internalType": "uint256",
// "name": "",
// "type": "uint256"
// }
// ],
// "stateMutability": "view",
// "type": "function"
// },
//
// {
// "inputs": [],
// "stateMutability": "nonpayable",
// "type": "constructor"
// },
// {
// "inputs": [
// {
// "internalType": "uint256[]",
// "name": "_a",
// "type": "uint256[]"
// },
// {
// "internalType": "address[]",
// "name": "_addr",
// "type": "address[]"
// }
// ],
// "name": "f1",
// "outputs": [],
// "stateMutability": "nonpayable",
// "type": "function"
// },
// {
// "inputs": [],
// "name": "f2",
// "outputs": [
// {
// "internalType": "uint256",
// "name": "",
// "type": "uint256"
// }
// ],
// "stateMutability": "view",
// "type": "function"
// },
//
// ......
// ]
type AbiData struct {
Expand Down
2 changes: 1 addition & 1 deletion cmd/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func getGasPrice(client *ethclient.Client) (*big.Int, error) {
var transferCmd = &cobra.Command{
Use: "transfer target-address amount",
Short: "Transfer amount of eth to target-address",
Long: "Transfer amount of eth to target-address, special word `all` is valid amount. unit is ether, can be changed by --unit.",
Long: "Transfer amount of eth to target-address, special word `all` is valid amount. unit is ether, can be changed by --unit.",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("requires target-address and amount")
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ module github.com/10gic/ethutil
go 1.13

require (
github.com/ethereum/go-ethereum v1.10.25
github.com/shopspring/decimal v1.2.0
github.com/spf13/cobra v1.1.3
github.com/ethereum/go-ethereum v1.11.2
github.com/shopspring/decimal v1.3.1
github.com/spf13/cobra v1.6.1
github.com/tyler-smith/go-bip32 v1.0.0
github.com/tyler-smith/go-bip39 v1.1.0
)
Loading

0 comments on commit 4693d7b

Please sign in to comment.