forked from cerc-io/laconicd-deprecated
evm: update error format (#350)
* return geth error format * fix format in gasestimate * deal with other evm errors * fix import * fix lint * add test Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
parent
695027cb2a
commit
63aa0de1e8
@ -8,6 +8,10 @@ import (
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
@ -26,7 +30,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"github.com/tharsis/ethermint/crypto/hd"
|
||||
@ -559,18 +562,12 @@ func (e *PublicAPI) doCall(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(res.VmError) > 0 {
|
||||
if res.VmError == vm.ErrExecutionReverted.Error() {
|
||||
return nil, evmtypes.NewExecErrorWithReason(res.Ret)
|
||||
}
|
||||
return nil, errors.New(res.VmError)
|
||||
}
|
||||
|
||||
if res.Failed() {
|
||||
if res.VmError == vm.ErrExecutionReverted.Error() {
|
||||
return nil, evmtypes.NewExecErrorWithReason(res.Ret)
|
||||
if res.VmError != vm.ErrExecutionReverted.Error() {
|
||||
return nil, status.Error(codes.Internal, res.VmError)
|
||||
}
|
||||
return nil, errors.New(res.VmError)
|
||||
return nil, evmtypes.NewExecErrorWithReason(res.Ret)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
|
@ -405,7 +405,7 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
|
||||
|
||||
// Binary search the gas requirement, as it may be higher than the amount used
|
||||
var (
|
||||
lo uint64 = ethparams.TxGas - 1
|
||||
lo = ethparams.TxGas - 1
|
||||
hi uint64
|
||||
cap uint64
|
||||
)
|
||||
@ -478,7 +478,7 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
|
||||
if failed {
|
||||
if result != nil && result.VmError != vm.ErrOutOfGas.Error() {
|
||||
if result.VmError == vm.ErrExecutionReverted.Error() {
|
||||
return nil, status.Error(codes.Internal, types.NewExecErrorWithReason(result.Ret).Error())
|
||||
return nil, types.NewExecErrorWithReason(result.Ret)
|
||||
}
|
||||
return nil, status.Error(codes.Internal, result.VmError)
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
@ -75,12 +79,33 @@ var (
|
||||
|
||||
// NewExecErrorWithReason unpacks the revert return bytes and returns a wrapped error
|
||||
// with the return reason.
|
||||
func NewExecErrorWithReason(revertReason []byte) error {
|
||||
hexValue := hexutil.Encode(revertReason)
|
||||
reason, errUnpack := abi.UnpackRevert(revertReason)
|
||||
func NewExecErrorWithReason(revertReason []byte) *RevertError {
|
||||
var result = common.CopyBytes(revertReason)
|
||||
reason, errUnpack := abi.UnpackRevert(result)
|
||||
err := errors.New("execution reverted")
|
||||
if errUnpack == nil {
|
||||
return sdkerrors.Wrapf(ErrExecutionReverted, "%s: %s", reason, hexValue)
|
||||
err = fmt.Errorf("execution reverted: %v", reason)
|
||||
}
|
||||
return &RevertError{
|
||||
error: err,
|
||||
reason: hexutil.Encode(result),
|
||||
}
|
||||
|
||||
return sdkerrors.Wrapf(ErrExecutionReverted, "%s", hexValue)
|
||||
}
|
||||
|
||||
// RevertError is an API error that encompass an EVM revert with JSON error
|
||||
// code and a binary data blob.
|
||||
type RevertError struct {
|
||||
error
|
||||
reason string // revert reason hex encoded
|
||||
}
|
||||
|
||||
// ErrorCode returns the JSON error code for a revert.
|
||||
// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
|
||||
func (e *RevertError) ErrorCode() int {
|
||||
return 3
|
||||
}
|
||||
|
||||
// ErrorData returns the hex encoded revert reason.
|
||||
func (e *RevertError) ErrorData() interface{} {
|
||||
return e.reason
|
||||
}
|
||||
|
53
x/evm/types/errors_test.go
Normal file
53
x/evm/types/errors_test.go
Normal file
@ -0,0 +1,53 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/status-im/keycard-go/hexutils"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]
|
||||
|
||||
func TestNewExecErrorWithReason(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
errorMessage string
|
||||
revertReason []byte
|
||||
data string
|
||||
}{
|
||||
{
|
||||
"Empty reason",
|
||||
"execution reverted",
|
||||
nil,
|
||||
"0x",
|
||||
},
|
||||
{
|
||||
"With unpackable reason",
|
||||
"execution reverted",
|
||||
[]byte("a"),
|
||||
"0x61",
|
||||
},
|
||||
{
|
||||
"With packable reason but empty reason",
|
||||
"execution reverted",
|
||||
revertSelector,
|
||||
"0x08c379a0",
|
||||
},
|
||||
{
|
||||
"With packable reason with reason",
|
||||
"execution reverted: COUNTER_TOO_LOW",
|
||||
hexutils.HexToBytes("08C379A00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000F434F554E5445525F544F4F5F4C4F570000000000000000000000000000000000"),
|
||||
"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000f434f554e5445525f544f4f5f4c4f570000000000000000000000000000000000",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
errWithReason := NewExecErrorWithReason(tc.revertReason)
|
||||
require.Equal(t, tc.errorMessage, errWithReason.Error())
|
||||
require.Equal(t, tc.data, errWithReason.ErrorData())
|
||||
require.Equal(t, 3, errWithReason.ErrorCode())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user