Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions evmd/tests/ibc/ics20_precompile_transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import (
"github.com/cosmos/evm/evmd"
"github.com/cosmos/evm/evmd/tests/integration"
"github.com/cosmos/evm/precompiles/ics20"
chainutil "github.com/cosmos/evm/testutil"
evmibctesting "github.com/cosmos/evm/testutil/ibc"
evmante "github.com/cosmos/evm/x/vm/ante"
evmtypes "github.com/cosmos/evm/x/vm/types"
transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types"

Expand Down Expand Up @@ -299,8 +299,8 @@ func (suite *ICS20TransferTestSuite) TestHandleMsgTransfer() {
"INVALID-DENOM-HASH",
)
suite.Require().ErrorContains(err, vm.ErrExecutionReverted.Error())
revertErr := evmtypes.NewExecErrorWithReason(evmRes.Ret)
suite.Require().Contains(revertErr.ErrorData(), "invalid denom trace hash")
revertErr := chainutil.DecodeRevertReason(*evmRes)
suite.Require().Contains(revertErr.Error(), "invalid denom trace hash")

// denomHash query method
evmRes, err = evmAppB.EVMKeeper.CallEVM(
Expand Down Expand Up @@ -347,8 +347,8 @@ func (suite *ICS20TransferTestSuite) TestHandleMsgTransfer() {
"",
)
suite.Require().ErrorContains(err, vm.ErrExecutionReverted.Error())
revertErr = evmtypes.NewExecErrorWithReason(evmRes.Ret)
suite.Require().Contains(revertErr.ErrorData(), "invalid denomination for cross-chain transfer")
revertErr = chainutil.DecodeRevertReason(*evmRes)
suite.Require().Contains(revertErr.Error(), "invalid denomination for cross-chain transfer")
})
}
}
Expand Down
10 changes: 5 additions & 5 deletions evmd/tests/ibc/v2_ics20_precompile_transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import (
"github.com/cosmos/evm/evmd"
"github.com/cosmos/evm/evmd/tests/integration"
"github.com/cosmos/evm/precompiles/ics20"
chainutil "github.com/cosmos/evm/testutil"
evmibctesting "github.com/cosmos/evm/testutil/ibc"
evmante "github.com/cosmos/evm/x/vm/ante"
evmtypes "github.com/cosmos/evm/x/vm/types"
transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types"

Expand Down Expand Up @@ -305,8 +305,8 @@ func (suite *ICS20TransferV2TestSuite) TestHandleMsgTransfer() {
"INVALID-DENOM-HASH",
)
suite.Require().ErrorContains(err, vm.ErrExecutionReverted.Error())
revertErr := evmtypes.NewExecErrorWithReason(evmRes.Ret)
suite.Require().Contains(revertErr.ErrorData(), "invalid denom trace hash")
revertErr := chainutil.DecodeRevertReason(*evmRes)
suite.Require().Contains(revertErr.Error(), "invalid denom trace hash")

// denomHash query method
evmRes, err = evmAppB.EVMKeeper.CallEVM(
Expand Down Expand Up @@ -353,8 +353,8 @@ func (suite *ICS20TransferV2TestSuite) TestHandleMsgTransfer() {
"",
)
suite.Require().ErrorContains(err, vm.ErrExecutionReverted.Error())
revertErr = evmtypes.NewExecErrorWithReason(evmRes.Ret)
suite.Require().Contains(revertErr.ErrorData(), "invalid denomination for cross-chain transfer")
revertErr = chainutil.DecodeRevertReason(*evmRes)
suite.Require().Contains(revertErr.Error(), "invalid denomination for cross-chain transfer")
})
}
}
Expand Down
4 changes: 2 additions & 2 deletions testutil/integration/evm/factory/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
abcitypes "github.com/cometbft/cometbft/abci/types"

"github.com/cosmos/evm/precompiles/testutil"
chainutil "github.com/cosmos/evm/testutil"
basefactory "github.com/cosmos/evm/testutil/integration/base/factory"
"github.com/cosmos/evm/testutil/integration/evm/grpc"
"github.com/cosmos/evm/testutil/integration/evm/network"
Expand Down Expand Up @@ -209,8 +210,7 @@ func (tf *IntegrationTxFactory) checkEthTxResponse(res *abcitypes.ExecTxResult)
}

if evmRes.Failed() {
revertErr := evmtypes.NewExecErrorWithReason(evmRes.Ret)
return fmt.Errorf("tx failed with VmError: %v: %s", evmRes.VmError, revertErr.ErrorData())
return chainutil.DecodeRevertReason(evmRes)
}
return nil
}
27 changes: 27 additions & 0 deletions testutil/util.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package testutil

import (
"bytes"
"context"
"fmt"
"time"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common/hexutil"

"github.com/cosmos/evm/crypto/ethsecp256k1"
evmtypes "github.com/cosmos/evm/x/vm/types"

errorsmod "cosmossdk.io/errors"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
Expand Down Expand Up @@ -108,3 +116,22 @@ func CreateTx(ctx context.Context, txCfg client.TxConfig, priv cryptotypes.PrivK

return txBuilder.GetTx(), nil
}

func DecodeRevertReason(evmRes evmtypes.MsgEthereumTxResponse) error {
revertErr := evmtypes.NewExecErrorWithReason(evmRes.Ret)
hexData, ok := revertErr.ErrorData().(string)
if ok {
decodedBytes, err := hexutil.Decode(hexData)
if err == nil {
if len(decodedBytes) >= 4 && bytes.Equal(decodedBytes[:4], evmtypes.RevertSelector) {
var reason string
reason, err = abi.UnpackRevert(decodedBytes)
if err == nil {
return fmt.Errorf("tx failed with VmError: %v: %s", evmRes.VmError, reason)
}
}
}
return errorsmod.Wrap(err, "failed to decode revert data")
}
return fmt.Errorf("tx failed with VmError: %v: %s", evmRes.VmError, revertErr.ErrorData())
}
5 changes: 0 additions & 5 deletions x/vm/keeper/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,11 +444,6 @@ func (k *Keeper) ApplyMessageWithConfig(
// reset leftoverGas, to be used by the tracer
leftoverGas = msg.GasLimit - gasUsed

// if the execution reverted, we return the revert reason as the return data
if vmError == vm.ErrExecutionReverted.Error() {
ret = evm.Interpreter().ReturnData()
}

return &types.MsgEthereumTxResponse{
GasUsed: gasUsed,
VmError: vmError,
Expand Down
3 changes: 2 additions & 1 deletion x/vm/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"

errorsmod "cosmossdk.io/errors"
Expand Down Expand Up @@ -122,7 +123,7 @@ func NewExecErrorWithReason(revertReason []byte) *RevertError {
}
return &RevertError{
error: err,
reason: reason,
reason: hexutil.Encode(result),
}
}

Expand Down
51 changes: 51 additions & 0 deletions x/vm/types/errors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package types_test

import (
"testing"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require"

"github.com/cosmos/evm/x/vm/types"
)

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",
types.RevertSelector,
"0x08c379a0",
},
{
"With packable reason with reason",
"execution reverted: COUNTER_TOO_LOW",
hexutil.MustDecode("0x08C379A00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000F434F554E5445525F544F4F5F4C4F570000000000000000000000000000000000"),
"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000f434f554e5445525f544f4f5f4c4f570000000000000000000000000000000000",
},
}

for _, tc := range testCases {
errWithReason := types.NewExecErrorWithReason(tc.revertReason)
require.Equal(t, tc.errorMessage, errWithReason.Error())
require.Equal(t, tc.data, errWithReason.ErrorData())
require.Equal(t, 3, errWithReason.ErrorCode())
}
}
Loading