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" | 	"math/big" | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/ethereum/go-ethereum/core/vm" | ||||||
|  | 	"google.golang.org/grpc/codes" | ||||||
|  | 	"google.golang.org/grpc/status" | ||||||
|  | 
 | ||||||
| 	"github.com/pkg/errors" | 	"github.com/pkg/errors" | ||||||
| 	"github.com/spf13/viper" | 	"github.com/spf13/viper" | ||||||
| 	"github.com/tendermint/tendermint/libs/log" | 	"github.com/tendermint/tendermint/libs/log" | ||||||
| @ -26,7 +30,6 @@ import ( | |||||||
| 	"github.com/ethereum/go-ethereum/common" | 	"github.com/ethereum/go-ethereum/common" | ||||||
| 	"github.com/ethereum/go-ethereum/common/hexutil" | 	"github.com/ethereum/go-ethereum/common/hexutil" | ||||||
| 	ethtypes "github.com/ethereum/go-ethereum/core/types" | 	ethtypes "github.com/ethereum/go-ethereum/core/types" | ||||||
| 	"github.com/ethereum/go-ethereum/core/vm" |  | ||||||
| 	"github.com/ethereum/go-ethereum/crypto" | 	"github.com/ethereum/go-ethereum/crypto" | ||||||
| 
 | 
 | ||||||
| 	"github.com/tharsis/ethermint/crypto/hd" | 	"github.com/tharsis/ethermint/crypto/hd" | ||||||
| @ -559,18 +562,12 @@ func (e *PublicAPI) doCall( | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		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.Failed() { | ||||||
| 		if res.VmError == vm.ErrExecutionReverted.Error() { | 		if res.VmError != vm.ErrExecutionReverted.Error() { | ||||||
| 			return nil, evmtypes.NewExecErrorWithReason(res.Ret) | 			return nil, status.Error(codes.Internal, res.VmError) | ||||||
| 		} | 		} | ||||||
| 		return nil, errors.New(res.VmError) | 		return nil, evmtypes.NewExecErrorWithReason(res.Ret) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return res, nil | 	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
 | 	// Binary search the gas requirement, as it may be higher than the amount used
 | ||||||
| 	var ( | 	var ( | ||||||
| 		lo  uint64 = ethparams.TxGas - 1 | 		lo  = ethparams.TxGas - 1 | ||||||
| 		hi  uint64 | 		hi  uint64 | ||||||
| 		cap uint64 | 		cap uint64 | ||||||
| 	) | 	) | ||||||
| @ -478,7 +478,7 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type | |||||||
| 		if failed { | 		if failed { | ||||||
| 			if result != nil && result.VmError != vm.ErrOutOfGas.Error() { | 			if result != nil && result.VmError != vm.ErrOutOfGas.Error() { | ||||||
| 				if result.VmError == vm.ErrExecutionReverted.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) | 				return nil, status.Error(codes.Internal, result.VmError) | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -1,7 +1,11 @@ | |||||||
| package types | package types | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 
 | ||||||
| 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | 	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/accounts/abi" | ||||||
| 	"github.com/ethereum/go-ethereum/common/hexutil" | 	"github.com/ethereum/go-ethereum/common/hexutil" | ||||||
| @ -75,12 +79,33 @@ var ( | |||||||
| 
 | 
 | ||||||
| // NewExecErrorWithReason unpacks the revert return bytes and returns a wrapped error
 | // NewExecErrorWithReason unpacks the revert return bytes and returns a wrapped error
 | ||||||
| // with the return reason.
 | // with the return reason.
 | ||||||
| func NewExecErrorWithReason(revertReason []byte) error { | func NewExecErrorWithReason(revertReason []byte) *RevertError { | ||||||
| 	hexValue := hexutil.Encode(revertReason) | 	var result = common.CopyBytes(revertReason) | ||||||
| 	reason, errUnpack := abi.UnpackRevert(revertReason) | 	reason, errUnpack := abi.UnpackRevert(result) | ||||||
|  | 	err := errors.New("execution reverted") | ||||||
| 	if errUnpack == nil { | 	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