diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 397997ff..020c2b08 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -305,17 +305,17 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A k.appendToContractHistory(ctx, contractAddress, historyEntry) k.storeContractInfo(ctx, contractAddress, &contractInfo) - // dispatch submessages then messages - data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) - if err != nil { - return nil, nil, sdkerrors.Wrap(err, "dispatch") - } - ctx.EventManager().EmitEvent(sdk.NewEvent( types.EventTypeInstantiate, sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()), sdk.NewAttribute(types.AttributeKeyCodeID, strconv.FormatUint(codeID, 10)), )) + + data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) + if err != nil { + return nil, nil, sdkerrors.Wrap(err, "dispatch") + } + return contractAddress, data, nil } @@ -349,16 +349,16 @@ func (k Keeper) execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) } - // dispatch submessages then messages + ctx.EventManager().EmitEvent(sdk.NewEvent( + types.EventTypeExecute, + sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()), + )) + data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) if err != nil { return nil, sdkerrors.Wrap(err, "dispatch") } - ctx.EventManager().EmitEvent(sdk.NewEvent( - types.EventTypeExecute, - sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()), - )) return data, nil } @@ -418,17 +418,17 @@ func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller k.addToContractCodeSecondaryIndex(ctx, contractAddress, historyEntry) k.storeContractInfo(ctx, contractAddress, contractInfo) - // dispatch submessages then messages - data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) - if err != nil { - return nil, sdkerrors.Wrap(err, "dispatch") - } - ctx.EventManager().EmitEvent(sdk.NewEvent( types.EventTypeMigrate, sdk.NewAttribute(types.AttributeKeyCodeID, strconv.FormatUint(newCodeID, 10)), sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()), )) + + data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) + if err != nil { + return nil, sdkerrors.Wrap(err, "dispatch") + } + return data, nil } @@ -456,16 +456,16 @@ func (k Keeper) Sudo(ctx sdk.Context, contractAddress sdk.AccAddress, msg []byte return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) } - // dispatch submessages then messages + ctx.EventManager().EmitEvent(sdk.NewEvent( + types.EventTypeSudo, + sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()), + )) + data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) if err != nil { return nil, sdkerrors.Wrap(err, "dispatch") } - ctx.EventManager().EmitEvent(sdk.NewEvent( - types.EventTypeSudo, - sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()), - )) return data, nil } @@ -494,16 +494,16 @@ func (k Keeper) reply(ctx sdk.Context, contractAddress sdk.AccAddress, reply was return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) } - // dispatch submessages then messages + ctx.EventManager().EmitEvent(sdk.NewEvent( + types.EventTypeReply, + sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()), + )) + data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) if err != nil { return nil, sdkerrors.Wrap(err, "dispatch") } - ctx.EventManager().EmitEvent(sdk.NewEvent( - types.EventTypeReply, - sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()), - )) return data, nil } @@ -1072,12 +1072,19 @@ func NewDefaultWasmVMContractResponseHandler(md msgDispatcher) *DefaultWasmVMCon // Handle processes the data returned by a contract invocation. func (h DefaultWasmVMContractResponseHandler) Handle(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, messages []wasmvmtypes.SubMsg, origRspData []byte) ([]byte, error) { + em := sdk.NewEventManager() result := origRspData - switch rsp, err := h.md.DispatchSubmessages(ctx, contractAddr, ibcPort, messages); { + switch rsp, err := h.md.DispatchSubmessages(ctx.WithEventManager(em), contractAddr, ibcPort, messages); { case err != nil: return nil, sdkerrors.Wrap(err, "submessages") case rsp != nil: result = rsp } + // emit non message type events only + for _, e := range em.Events() { + if e.Type != sdk.EventTypeMessage { + ctx.EventManager().EmitEvent(e) + } + } return result, nil } diff --git a/x/wasm/keeper/keeper_test.go b/x/wasm/keeper/keeper_test.go index 4968985e..041a991c 100644 --- a/x/wasm/keeper/keeper_test.go +++ b/x/wasm/keeper/keeper_test.go @@ -309,10 +309,10 @@ func TestInstantiate(t *testing.T) { // and events emitted expEvt := sdk.Events{ - sdk.NewEvent("wasm", - sdk.NewAttribute("_contract_address", gotContractAddr.String()), sdk.NewAttribute("Let the", "hacking begin")), sdk.NewEvent("instantiate", sdk.NewAttribute("_contract_address", gotContractAddr.String()), sdk.NewAttribute("code_id", "1")), + sdk.NewEvent("wasm", + sdk.NewAttribute("_contract_address", gotContractAddr.String()), sdk.NewAttribute("Let the", "hacking begin")), } assert.Equal(t, expEvt, em.Events()) } @@ -546,10 +546,10 @@ func TestExecute(t *testing.T) { assert.Equal(t, sdk.Coins(nil), bankKeeper.GetAllBalances(ctx, contractAcct.GetAddress())) // and events emitted - require.Len(t, em.Events(), 7) + require.Len(t, em.Events(), 5) expEvt := sdk.NewEvent("execute", sdk.NewAttribute("_contract_address", addr.String())) - assert.Equal(t, expEvt, em.Events()[6]) + assert.Equal(t, expEvt, em.Events()[1]) t.Logf("Duration: %v (%d gas)\n", diff, gasAfter-gasBefore) } @@ -1035,6 +1035,13 @@ func TestMigrateWithDispatchedMessage(t *testing.T) { assert.Equal(t, "burnt 1 keys", string(data)) type dict map[string]interface{} expEvents := []dict{ + { + "Type": "migrate", + "Attr": []dict{ + {"code_id": "2"}, + {"_contract_address": contractAddr}, + }, + }, { "Type": "wasm", "Attr": []dict{ @@ -1051,25 +1058,6 @@ func TestMigrateWithDispatchedMessage(t *testing.T) { {"amount": "100000denom"}, }, }, - { - "Type": "message", - "Attr": []dict{ - {"sender": contractAddr}, - }, - }, - { - "Type": "message", - "Attr": []dict{ - {"module": "bank"}, - }, - }, - { - "Type": "migrate", - "Attr": []dict{ - {"code_id": "2"}, - {"_contract_address": contractAddr}, - }, - }, } expJSONEvts := string(mustMarshal(t, expEvents)) assert.JSONEq(t, expJSONEvts, prettyEvents(t, ctx.EventManager().Events()), prettyEvents(t, ctx.EventManager().Events())) @@ -1222,10 +1210,10 @@ func TestSudo(t *testing.T) { balance := bankKeeper.GetBalance(ctx, comAcct.GetAddress(), "denom") assert.Equal(t, sdk.NewInt64Coin("denom", 76543), balance) // and events emitted - require.Len(t, em.Events(), 4) + require.Len(t, em.Events(), 2) expEvt := sdk.NewEvent("sudo", sdk.NewAttribute("_contract_address", addr.String())) - assert.Equal(t, expEvt, em.Events()[3]) + assert.Equal(t, expEvt, em.Events()[0]) } @@ -1532,6 +1520,7 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { setup func(m *wasmtesting.MockMsgDispatcher) expErr bool expData []byte + expEvts sdk.Events }{ "submessage overwrites result when set": { srcData: []byte("otherData"), @@ -1542,6 +1531,7 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { }, expErr: false, expData: []byte("mySubMsgData"), + expEvts: sdk.Events{}, }, "submessage overwrites result when empty": { srcData: []byte("otherData"), @@ -1552,6 +1542,7 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { }, expErr: false, expData: []byte(""), + expEvts: sdk.Events{}, }, "submessage do not overwrite result when nil": { srcData: []byte("otherData"), @@ -1562,6 +1553,7 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { }, expErr: false, expData: []byte("otherData"), + expEvts: sdk.Events{}, }, "submessage error aborts process": { setup: func(m *wasmtesting.MockMsgDispatcher) { @@ -1571,6 +1563,24 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { }, expErr: true, }, + "message events filtered out": { + setup: func(m *wasmtesting.MockMsgDispatcher) { + m.DispatchSubmessagesFn = func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) { + ctx.EventManager().EmitEvent(sdk.NewEvent(sdk.EventTypeMessage)) + return nil, nil + } + }, + expEvts: sdk.Events{}, + }, + "message emit non message events": { + setup: func(m *wasmtesting.MockMsgDispatcher) { + m.DispatchSubmessagesFn = func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) { + ctx.EventManager().EmitEvent(sdk.NewEvent("myEvent")) + return nil, nil + } + }, + expEvts: sdk.Events{sdk.NewEvent("myEvent")}, + }, } for name, spec := range specs { t.Run(name, func(t *testing.T) { @@ -1580,15 +1590,17 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { var mock wasmtesting.MockMsgDispatcher spec.setup(&mock) d := NewDefaultWasmVMContractResponseHandler(&mock) - // when + em := sdk.NewEventManager() - gotData, gotErr := d.Handle(sdk.Context{}, RandomAccountAddress(t), "ibc-port", msgs, spec.srcData) + // when + gotData, gotErr := d.Handle(sdk.Context{}.WithEventManager(em), RandomAccountAddress(t), "ibc-port", msgs, spec.srcData) if spec.expErr { require.Error(t, gotErr) return } require.NoError(t, gotErr) assert.Equal(t, spec.expData, gotData) + assert.Equal(t, spec.expEvts, em.Events()) }) } } diff --git a/x/wasm/keeper/msg_server.go b/x/wasm/keeper/msg_server.go index 5d4862f4..324b99dc 100644 --- a/x/wasm/keeper/msg_server.go +++ b/x/wasm/keeper/msg_server.go @@ -23,10 +23,6 @@ func (m msgServer) StoreCode(goCtx context.Context, msg *types.MsgStoreCode) (*t if err != nil { return nil, sdkerrors.Wrap(err, "sender") } - codeID, err := m.keeper.Create(ctx, senderAddr, msg.WASMByteCode, msg.InstantiatePermission) - if err != nil { - return nil, err - } ctx.EventManager().EmitEvent(sdk.NewEvent( sdk.EventTypeMessage, @@ -34,6 +30,11 @@ func (m msgServer) StoreCode(goCtx context.Context, msg *types.MsgStoreCode) (*t sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), )) + codeID, err := m.keeper.Create(ctx, senderAddr, msg.WASMByteCode, msg.InstantiatePermission) + if err != nil { + return nil, err + } + return &types.MsgStoreCodeResponse{ CodeID: codeID, }, nil @@ -53,17 +54,17 @@ func (m msgServer) InstantiateContract(goCtx context.Context, msg *types.MsgInst } } - contractAddr, data, err := m.keeper.Instantiate(ctx, msg.CodeID, senderAddr, adminAddr, msg.Msg, msg.Label, msg.Funds) - if err != nil { - return nil, err - } - ctx.EventManager().EmitEvent(sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), )) + contractAddr, data, err := m.keeper.Instantiate(ctx, msg.CodeID, senderAddr, adminAddr, msg.Msg, msg.Label, msg.Funds) + if err != nil { + return nil, err + } + return &types.MsgInstantiateContractResponse{ Address: contractAddr.String(), Data: data, @@ -81,17 +82,17 @@ func (m msgServer) ExecuteContract(goCtx context.Context, msg *types.MsgExecuteC return nil, sdkerrors.Wrap(err, "contract") } - data, err := m.keeper.Execute(ctx, contractAddr, senderAddr, msg.Msg, msg.Funds) - if err != nil { - return nil, err - } - ctx.EventManager().EmitEvent(sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), )) + data, err := m.keeper.Execute(ctx, contractAddr, senderAddr, msg.Msg, msg.Funds) + if err != nil { + return nil, err + } + return &types.MsgExecuteContractResponse{ Data: data, }, nil @@ -108,17 +109,17 @@ func (m msgServer) MigrateContract(goCtx context.Context, msg *types.MsgMigrateC return nil, sdkerrors.Wrap(err, "contract") } - data, err := m.keeper.Migrate(ctx, contractAddr, senderAddr, msg.CodeID, msg.Msg) - if err != nil { - return nil, err - } - ctx.EventManager().EmitEvent(sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), )) + data, err := m.keeper.Migrate(ctx, contractAddr, senderAddr, msg.CodeID, msg.Msg) + if err != nil { + return nil, err + } + return &types.MsgMigrateContractResponse{ Data: data, }, nil @@ -139,16 +140,16 @@ func (m msgServer) UpdateAdmin(goCtx context.Context, msg *types.MsgUpdateAdmin) return nil, sdkerrors.Wrap(err, "new admin") } - if err := m.keeper.UpdateContractAdmin(ctx, contractAddr, senderAddr, newAdminAddr); err != nil { - return nil, err - } - ctx.EventManager().EmitEvent(sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), )) + if err := m.keeper.UpdateContractAdmin(ctx, contractAddr, senderAddr, newAdminAddr); err != nil { + return nil, err + } + return &types.MsgUpdateAdminResponse{}, nil } @@ -163,15 +164,15 @@ func (m msgServer) ClearAdmin(goCtx context.Context, msg *types.MsgClearAdmin) ( return nil, sdkerrors.Wrap(err, "contract") } - if err := m.keeper.ClearContractAdmin(ctx, contractAddr, senderAddr); err != nil { - return nil, err - } - ctx.EventManager().EmitEvent(sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), )) + if err := m.keeper.ClearContractAdmin(ctx, contractAddr, senderAddr); err != nil { + return nil, err + } + return &types.MsgClearAdminResponse{}, nil } diff --git a/x/wasm/keeper/proposal_integration_test.go b/x/wasm/keeper/proposal_integration_test.go index 0d73cb9b..ea83e69f 100644 --- a/x/wasm/keeper/proposal_integration_test.go +++ b/x/wasm/keeper/proposal_integration_test.go @@ -112,8 +112,8 @@ func TestInstantiateProposal(t *testing.T) { assert.Equal(t, expHistory, wasmKeeper.GetContractHistory(ctx, contractAddr)) // and event require.Len(t, em.Events(), 3, "%#v", em.Events()) - require.Equal(t, types.WasmModuleEventType, em.Events()[0].Type) - require.Equal(t, types.EventTypeInstantiate, em.Events()[1].Type) + require.Equal(t, types.EventTypeInstantiate, em.Events()[0].Type) + require.Equal(t, types.WasmModuleEventType, em.Events()[1].Type) require.Equal(t, types.EventTypeGovContractResult, em.Events()[2].Type) require.Len(t, em.Events()[2].Attributes, 1) require.NotEmpty(t, em.Events()[2].Attributes[0]) diff --git a/x/wasm/module_test.go b/x/wasm/module_test.go index 988fe5fe..2e5d9809 100644 --- a/x/wasm/module_test.go +++ b/x/wasm/module_test.go @@ -180,11 +180,11 @@ func TestHandleInstantiate(t *testing.T) { require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", contractBech32Addr) // this should be standard x/wasm init event, nothing from contract require.Equal(t, 3, len(res.Events), prettyEvents(res.Events)) - require.Equal(t, "wasm", res.Events[0].Type) - assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[0].Attributes[0]) + require.Equal(t, "message", res.Events[0].Type) + assertAttribute(t, "module", "wasm", res.Events[0].Attributes[0]) require.Equal(t, "instantiate", res.Events[1].Type) - require.Equal(t, "message", res.Events[2].Type) - assertAttribute(t, "module", "wasm", res.Events[2].Attributes[0]) + require.Equal(t, "wasm", res.Events[2].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[2].Attributes[0]) assertCodeList(t, q, data.ctx, 1) assertCodeBytes(t, q, data.ctx, 1, testContract) @@ -238,12 +238,12 @@ func TestHandleExecute(t *testing.T) { require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", contractBech32Addr) // this should be standard x/wasm message event, init event, plus a bank send event (2), with no custom contract events require.Equal(t, 4, len(res.Events), prettyEvents(res.Events)) - require.Equal(t, "transfer", res.Events[0].Type) - require.Equal(t, "wasm", res.Events[1].Type) - assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[1].Attributes[0]) + require.Equal(t, "message", res.Events[0].Type) + assertAttribute(t, "module", "wasm", res.Events[0].Attributes[0]) + require.Equal(t, "transfer", res.Events[1].Type) require.Equal(t, "instantiate", res.Events[2].Type) - require.Equal(t, "message", res.Events[3].Type) - assertAttribute(t, "module", "wasm", res.Events[3].Attributes[0]) + require.Equal(t, "wasm", res.Events[3].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[3].Attributes[0]) // ensure bob doesn't exist bobAcct := data.acctKeeper.GetAccount(data.ctx, bob) @@ -275,28 +275,31 @@ func TestHandleExecute(t *testing.T) { // this should be standard message event, plus x/wasm init event, plus 2 bank send event, plus a special event from the contract require.Equal(t, 6, len(res.Events), prettyEvents(res.Events)) - require.Equal(t, "transfer", res.Events[0].Type) - require.Len(t, res.Events[0].Attributes, 3) - assertAttribute(t, "recipient", contractBech32Addr, res.Events[0].Attributes[0]) - assertAttribute(t, "sender", fred.String(), res.Events[0].Attributes[1]) - assertAttribute(t, "amount", "5000denom", res.Events[0].Attributes[2]) + assert.Equal(t, "message", res.Events[0].Type) + assertAttribute(t, "module", "wasm", res.Events[0].Attributes[0]) + + require.Equal(t, "transfer", res.Events[1].Type) + require.Len(t, res.Events[1].Attributes, 3) + assertAttribute(t, "recipient", contractBech32Addr, res.Events[1].Attributes[0]) + assertAttribute(t, "sender", fred.String(), res.Events[1].Attributes[1]) + assertAttribute(t, "amount", "5000denom", res.Events[1].Attributes[2]) + + assert.Equal(t, "execute", res.Events[2].Type) + // custom contract event attribute - assert.Equal(t, "wasm", res.Events[1].Type) - assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[1].Attributes[0]) - assertAttribute(t, "action", "release", res.Events[1].Attributes[1]) + assert.Equal(t, "wasm", res.Events[3].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[3].Attributes[0]) + assertAttribute(t, "action", "release", res.Events[3].Attributes[1]) // custom contract event - assert.Equal(t, "wasm-hackatom", res.Events[2].Type) - assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[1].Attributes[0]) - assertAttribute(t, "action", "release", res.Events[1].Attributes[1]) + assert.Equal(t, "wasm-hackatom", res.Events[4].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[4].Attributes[0]) + assertAttribute(t, "action", "release", res.Events[4].Attributes[1]) // second transfer (this without conflicting message) - assert.Equal(t, "transfer", res.Events[3].Type) - assertAttribute(t, "recipient", bob.String(), res.Events[3].Attributes[0]) - assertAttribute(t, "sender", contractBech32Addr, res.Events[3].Attributes[1]) - assertAttribute(t, "amount", "105000denom", res.Events[3].Attributes[2]) + assert.Equal(t, "transfer", res.Events[5].Type) + assertAttribute(t, "recipient", bob.String(), res.Events[5].Attributes[0]) + assertAttribute(t, "sender", contractBech32Addr, res.Events[5].Attributes[1]) + assertAttribute(t, "amount", "105000denom", res.Events[5].Attributes[2]) // finally, standard x/wasm tag - assert.Equal(t, "execute", res.Events[4].Type) - assert.Equal(t, "message", res.Events[5].Type) - assertAttribute(t, "module", "wasm", res.Events[5].Attributes[0]) // ensure bob now exists and got both payments released bobAcct = data.acctKeeper.GetAccount(data.ctx, bob)