add error codes to calls

This commit is contained in:
Sina Mahmoodi 2023-10-04 16:11:49 +03:00
parent 523e3d24fa
commit d5c0ff4eae
3 changed files with 91 additions and 7 deletions

View file

@ -1218,7 +1218,7 @@ type callResult struct {
Logs []*types.Log `json:"logs"`
GasUsed hexutil.Uint64 `json:"gasUsed"`
Status hexutil.Uint64 `json:"status"`
Error string `json:"error,omitempty"`
Error *callError `json:"error,omitempty"`
}
func (r *callResult) MarshalJSON() ([]byte, error) {
@ -1326,7 +1326,8 @@ func (s *BlockChainAPI) MulticallV1(ctx context.Context, opts multicallOpts, blo
}
result, err := applyMessage(ctx, s.b, call, state, header, timeout, gp, &blockContext, vmConfig, precompiles, opts.Validation)
if err != nil {
results[bi].Calls[i] = callResult{Error: err.Error(), Status: hexutil.Uint64(types.ReceiptStatusFailed)}
callErr := callErrorFromError(err)
results[bi].Calls[i] = callResult{Error: callErr, Status: hexutil.Uint64(types.ReceiptStatusFailed)}
continue
}
// If the result contains a revert reason, try to unpack it.
@ -1337,7 +1338,11 @@ func (s *BlockChainAPI) MulticallV1(ctx context.Context, opts multicallOpts, blo
callRes := callResult{ReturnValue: result.Return(), Logs: logs, GasUsed: hexutil.Uint64(result.UsedGas)}
if result.Failed() {
callRes.Status = hexutil.Uint64(types.ReceiptStatusFailed)
callRes.Error = result.Err.Error()
if errors.Is(result.Err, vm.ErrExecutionReverted) {
callRes.Error = &callError{Message: result.Err.Error(), Code: -32000}
} else {
callRes.Error = &callError{Message: result.Err.Error(), Code: -32015}
}
} else {
callRes.Status = hexutil.Uint64(types.ReceiptStatusSuccessful)
}

View file

@ -991,9 +991,13 @@ func TestMulticallV1(t *testing.T) {
BlockHash common.Hash `json:"blockHash"`
Index hexutil.Uint `json:"logIndex"`
}
type callErr struct {
Message string
Code int
}
type callRes struct {
ReturnValue string `json:"returnData"`
Error string
Error callErr
Logs []log
GasUsed string
Status string
@ -1043,7 +1047,7 @@ func TestMulticallV1(t *testing.T) {
Number: "0xb",
Hash: n11hash,
GasLimit: "0x47e7c4",
GasUsed: "0xa410",
GasUsed: "0xf618",
FeeRecipient: coinbase,
Calls: []callRes{{
ReturnValue: "0x",
@ -1055,6 +1059,11 @@ func TestMulticallV1(t *testing.T) {
GasUsed: "0x5208",
Logs: []log{},
Status: "0x1",
}, {
ReturnValue: "0x",
GasUsed: "0x5208",
Logs: []log{},
Status: "0x1",
}},
}},
}, {
@ -1125,7 +1134,7 @@ func TestMulticallV1(t *testing.T) {
GasUsed: "0x0",
Logs: []log{},
Status: "0x0",
Error: fmt.Sprintf("err: insufficient funds for gas * price + value: address %s have 0 want 1000 (supplied gas 4691388)", randomAccounts[3].addr.String()),
Error: callErr{Message: fmt.Sprintf("err: insufficient funds for gas * price + value: address %s have 0 want 1000 (supplied gas 4691388)", randomAccounts[3].addr.String()), Code: errCodeInsufficientFunds},
}},
}},
}, {
@ -1576,7 +1585,7 @@ func TestMulticallV1(t *testing.T) {
GasUsed: "0x0",
Logs: []log{},
Status: "0x0",
Error: fmt.Sprintf("err: nonce too high: address %s, tx: 2 state: 0 (supplied gas 4712388)", accounts[2].addr),
Error: callErr{Message: fmt.Sprintf("err: nonce too high: address %s, tx: 2 state: 0 (supplied gas 4712388)", accounts[2].addr), Code: errCodeNonceTooHigh},
}},
}},
},

70
internal/ethapi/errors.go Normal file
View file

@ -0,0 +1,70 @@
// Copyright 2023 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 ethapi
import (
"errors"
"github.com/ethereum/go-ethereum/core"
)
type callError struct {
Message string `json:"message"`
Code int `json:"code"`
}
const (
errCodeNonceTooHigh = -38011
errCodeNonceTooLow = -38010
errCodeInsufficientFunds = -38014
errCodeIntrinsicGas = -38013
errCodeInternalError = -32603
errCodeInvalidParams = -32602
)
func callErrorFromError(err error) *callError {
if err == nil {
return nil
}
switch {
case errors.Is(err, core.ErrNonceTooHigh):
return &callError{Message: err.Error(), Code: errCodeNonceTooHigh}
case errors.Is(err, core.ErrNonceTooLow):
return &callError{Message: err.Error(), Code: errCodeNonceTooLow}
case errors.Is(err, core.ErrSenderNoEOA):
// TODO
case errors.Is(err, core.ErrFeeCapVeryHigh):
return &callError{Message: err.Error(), Code: errCodeInvalidParams}
case errors.Is(err, core.ErrTipVeryHigh):
return &callError{Message: err.Error(), Code: errCodeInvalidParams}
case errors.Is(err, core.ErrTipAboveFeeCap):
return &callError{Message: err.Error(), Code: errCodeInvalidParams}
case errors.Is(err, core.ErrFeeCapTooLow):
// TODO
return &callError{Message: err.Error(), Code: errCodeInvalidParams}
case errors.Is(err, core.ErrInsufficientFunds):
return &callError{Message: err.Error(), Code: errCodeInsufficientFunds}
case errors.Is(err, core.ErrIntrinsicGas):
return &callError{Message: err.Error(), Code: errCodeIntrinsicGas}
case errors.Is(err, core.ErrInsufficientFundsForTransfer):
return &callError{Message: err.Error(), Code: errCodeInsufficientFunds}
}
return &callError{
Message: err.Error(),
Code: errCodeInternalError,
}
}