diff --git a/app/ante.go b/app/ante.go index 0ccb6cd3c4..905420a683 100644 --- a/app/ante.go +++ b/app/ante.go @@ -104,6 +104,7 @@ func NewAnteHandlerAndDepGenerator(options HandlerOptions) (sdk.AnteHandler, sdk sdk.CustomDepWrappedAnteDecorator(sequentialVerifyDecorator, depdecorators.SignerDepDecorator{ReadOnly: true}), sdk.CustomDepWrappedAnteDecorator(ante.NewIncrementSequenceDecorator(options.AccountKeeper), depdecorators.SignerDepDecorator{ReadOnly: false}), sdk.DefaultWrappedAnteDecorator(evmante.NewEVMAddressDecorator(options.EVMKeeper, options.EVMKeeper.AccountKeeper())), + sdk.DefaultWrappedAnteDecorator(antedecorators.NewAuthzNestedMessageDecorator()), sdk.DefaultWrappedAnteDecorator(ibcante.NewAnteDecorator(options.IBCKeeper)), sdk.DefaultWrappedAnteDecorator(dex.NewTickSizeMultipleDecorator(*options.DexKeeper)), dex.NewCheckDexGasDecorator(*options.DexKeeper, options.CheckTxMemState), diff --git a/app/antedecorators/authz_nested_message.go b/app/antedecorators/authz_nested_message.go new file mode 100644 index 0000000000..a7d4957e96 --- /dev/null +++ b/app/antedecorators/authz_nested_message.go @@ -0,0 +1,63 @@ +package antedecorators + +import ( + "errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz" + evmtypes "github.com/sei-protocol/sei-chain/x/evm/types" +) + +type AuthzNestedMessageDecorator struct{} + +func NewAuthzNestedMessageDecorator() AuthzNestedMessageDecorator { + return AuthzNestedMessageDecorator{} +} + +func (ad AuthzNestedMessageDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + for _, msg := range tx.GetMsgs() { + switch m := msg.(type) { + case *authz.MsgExec: + // find nested evm messages + containsEvm, err := ad.CheckAuthzContainsEvm(ctx, m) + if err != nil { + return ctx, err + } + if containsEvm { + return ctx, errors.New("permission denied, authz tx contains evm message") + } + default: + continue + } + } + + return next(ctx, tx, simulate) +} + +func (ad AuthzNestedMessageDecorator) CheckAuthzContainsEvm(ctx sdk.Context, authzMsg *authz.MsgExec) (bool, error) { + msgs, err := authzMsg.GetMessages() + if err != nil { + return false, err + } + for _, msg := range msgs { + // check if message type is authz exec or evm + switch m := msg.(type) { + case *evmtypes.MsgEVMTransaction: + return true, nil + case *authz.MsgExec: + // find nested to check for evm + valid, err := ad.CheckAuthzContainsEvm(ctx, m) + + if err != nil { + return false, err + } + + if valid { + return true, nil + } + default: + continue + } + } + return false, nil +} diff --git a/app/antedecorators/authz_nested_message_test.go b/app/antedecorators/authz_nested_message_test.go new file mode 100644 index 0000000000..a1da2ea600 --- /dev/null +++ b/app/antedecorators/authz_nested_message_test.go @@ -0,0 +1,58 @@ +package antedecorators_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/sei-protocol/sei-chain/app/antedecorators" + evmtypes "github.com/sei-protocol/sei-chain/x/evm/types" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto/secp256k1" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" +) + +func TestAuthzNestedEvmMessage(t *testing.T) { + priv1 := secp256k1.GenPrivKey() + addr1 := sdk.AccAddress(priv1.PubKey().Address()) + output = "" + anteDecorators := []sdk.AnteFullDecorator{ + sdk.DefaultWrappedAnteDecorator(antedecorators.NewAuthzNestedMessageDecorator()), + } + ctx := sdk.NewContext(nil, tmproto.Header{}, false, nil) + chainedHandler, _ := sdk.ChainAnteDecorators(anteDecorators...) + + nestedEvmMessage := authz.NewMsgExec(addr1, []sdk.Msg{&evmtypes.MsgEVMTransaction{}}) + // test with nested evm message + _, err := chainedHandler( + ctx.WithPriority(0), + FakeTx{ + FakeMsgs: []sdk.Msg{&nestedEvmMessage}, + }, + false, + ) + require.NotNil(t, err) + + // Multiple nested layers to evm message + doubleNestedEvmMessage := authz.NewMsgExec(addr1, []sdk.Msg{&nestedEvmMessage}) + _, err = chainedHandler( + ctx.WithPriority(0), + FakeTx{ + FakeMsgs: []sdk.Msg{&doubleNestedEvmMessage}, + }, + false, + ) + require.NotNil(t, err) + + // No error + nestedMessage := authz.NewMsgExec(addr1, []sdk.Msg{&banktypes.MsgSend{}}) + _, err = chainedHandler( + ctx.WithPriority(0), + FakeTx{ + FakeMsgs: []sdk.Msg{&nestedMessage}, + }, + false, + ) + require.Nil(t, err) +}