mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
add error codes to calls
This commit is contained in:
parent
523e3d24fa
commit
d5c0ff4eae
3 changed files with 91 additions and 7 deletions
|
|
@ -1218,7 +1218,7 @@ type callResult struct {
|
||||||
Logs []*types.Log `json:"logs"`
|
Logs []*types.Log `json:"logs"`
|
||||||
GasUsed hexutil.Uint64 `json:"gasUsed"`
|
GasUsed hexutil.Uint64 `json:"gasUsed"`
|
||||||
Status hexutil.Uint64 `json:"status"`
|
Status hexutil.Uint64 `json:"status"`
|
||||||
Error string `json:"error,omitempty"`
|
Error *callError `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *callResult) MarshalJSON() ([]byte, error) {
|
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)
|
result, err := applyMessage(ctx, s.b, call, state, header, timeout, gp, &blockContext, vmConfig, precompiles, opts.Validation)
|
||||||
if err != nil {
|
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
|
continue
|
||||||
}
|
}
|
||||||
// If the result contains a revert reason, try to unpack it.
|
// 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)}
|
callRes := callResult{ReturnValue: result.Return(), Logs: logs, GasUsed: hexutil.Uint64(result.UsedGas)}
|
||||||
if result.Failed() {
|
if result.Failed() {
|
||||||
callRes.Status = hexutil.Uint64(types.ReceiptStatusFailed)
|
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 {
|
} else {
|
||||||
callRes.Status = hexutil.Uint64(types.ReceiptStatusSuccessful)
|
callRes.Status = hexutil.Uint64(types.ReceiptStatusSuccessful)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -991,9 +991,13 @@ func TestMulticallV1(t *testing.T) {
|
||||||
BlockHash common.Hash `json:"blockHash"`
|
BlockHash common.Hash `json:"blockHash"`
|
||||||
Index hexutil.Uint `json:"logIndex"`
|
Index hexutil.Uint `json:"logIndex"`
|
||||||
}
|
}
|
||||||
|
type callErr struct {
|
||||||
|
Message string
|
||||||
|
Code int
|
||||||
|
}
|
||||||
type callRes struct {
|
type callRes struct {
|
||||||
ReturnValue string `json:"returnData"`
|
ReturnValue string `json:"returnData"`
|
||||||
Error string
|
Error callErr
|
||||||
Logs []log
|
Logs []log
|
||||||
GasUsed string
|
GasUsed string
|
||||||
Status string
|
Status string
|
||||||
|
|
@ -1043,7 +1047,7 @@ func TestMulticallV1(t *testing.T) {
|
||||||
Number: "0xb",
|
Number: "0xb",
|
||||||
Hash: n11hash,
|
Hash: n11hash,
|
||||||
GasLimit: "0x47e7c4",
|
GasLimit: "0x47e7c4",
|
||||||
GasUsed: "0xa410",
|
GasUsed: "0xf618",
|
||||||
FeeRecipient: coinbase,
|
FeeRecipient: coinbase,
|
||||||
Calls: []callRes{{
|
Calls: []callRes{{
|
||||||
ReturnValue: "0x",
|
ReturnValue: "0x",
|
||||||
|
|
@ -1055,6 +1059,11 @@ func TestMulticallV1(t *testing.T) {
|
||||||
GasUsed: "0x5208",
|
GasUsed: "0x5208",
|
||||||
Logs: []log{},
|
Logs: []log{},
|
||||||
Status: "0x1",
|
Status: "0x1",
|
||||||
|
}, {
|
||||||
|
ReturnValue: "0x",
|
||||||
|
GasUsed: "0x5208",
|
||||||
|
Logs: []log{},
|
||||||
|
Status: "0x1",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
|
|
@ -1125,7 +1134,7 @@ func TestMulticallV1(t *testing.T) {
|
||||||
GasUsed: "0x0",
|
GasUsed: "0x0",
|
||||||
Logs: []log{},
|
Logs: []log{},
|
||||||
Status: "0x0",
|
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",
|
GasUsed: "0x0",
|
||||||
Logs: []log{},
|
Logs: []log{},
|
||||||
Status: "0x0",
|
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
70
internal/ethapi/errors.go
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue