diff --git a/x/wasm/ibc.go b/x/wasm/ibc.go index b310e04cc9..977f2a0611 100644 --- a/x/wasm/ibc.go +++ b/x/wasm/ibc.go @@ -264,26 +264,26 @@ func (i IBCHandler) OnRecvPacket( ) ibcexported.Acknowledgement { contractAddr, err := ContractFromPortID(packet.DestinationPort) if err != nil { - return channeltypes.NewErrorAcknowledgement(errorsmod.Wrapf(err, "contract port id")) + // this must not happen as ports were registered before + panic(errorsmod.Wrapf(err, "contract port id")) } + + em := sdk.NewEventManager() msg := wasmvmtypes.IBCPacketReceiveMsg{Packet: newIBCPacket(packet), Relayer: relayer.String()} - ack, err := i.keeper.OnRecvPacket(ctx, contractAddr, msg) + ack, err := i.keeper.OnRecvPacket(ctx.WithEventManager(em), contractAddr, msg) if err != nil { - return channeltypes.NewErrorAcknowledgement(err) - } - return ContractConfirmStateAck(ack) -} - -var _ ibcexported.Acknowledgement = ContractConfirmStateAck{} - -type ContractConfirmStateAck []byte - -func (w ContractConfirmStateAck) Success() bool { - return true // always commit state -} - -func (w ContractConfirmStateAck) Acknowledgement() []byte { - return w + ack = channeltypes.NewErrorAcknowledgement(err) + types.EmitAcknowledgementEvent(ctx, contractAddr, ack, err) + // the state gets reverted, so we drop all captured events + return ack + } + if ack == nil || ack.Success() { + // emit all contract and submessage events on success + // nil ack is a success case, see: https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/keeper/msg_server.go#L453 + ctx.EventManager().EmitEvents(em.Events()) + } + types.EmitAcknowledgementEvent(ctx, contractAddr, ack, nil) + return ack } // OnAcknowledgementPacket implements the IBCModule interface diff --git a/x/wasm/ibc_test.go b/x/wasm/ibc_test.go index a92d451453..88cdd34929 100644 --- a/x/wasm/ibc_test.go +++ b/x/wasm/ibc_test.go @@ -4,11 +4,125 @@ import ( "testing" wasmvmtypes "github.com/CosmWasm/wasmvm/types" + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/libs/rand" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/CosmWasm/wasmd/x/wasm/keeper" + "github.com/CosmWasm/wasmd/x/wasm/types" ) +func TestOnRecvPacket(t *testing.T) { + anyRelayerAddr := sdk.AccAddress(rand.Bytes(address.Len)) + anyContractIBCPkg := IBCPacketFixture(func(p *channeltypes.Packet) { + p.DestinationPort = "wasm.cosmos1w09vr7rpe2agu0kg2zlpkdckce865l3zps8mxjurxthfh3m7035qe5hh7f" + }) + myCustomEvent := sdk.NewEvent("testing") + specs := map[string]struct { + ibcPkg channeltypes.Packet + contractRsp ibcexported.Acknowledgement + contractErr error + expEvents sdk.Events + expPanic bool + expAck ibcexported.Acknowledgement + }{ + "contract returns success response": { + ibcPkg: anyContractIBCPkg, + contractRsp: keeper.ContractConfirmStateAck([]byte{1}), + expAck: keeper.ContractConfirmStateAck([]byte{1}), + expEvents: sdk.Events{ + myCustomEvent, + { + Type: "ibc_packet_received", + Attributes: []abci.EventAttribute{ + {Key: "module", Value: "wasm"}, + {Key: "_contract_address", Value: "cosmos1w09vr7rpe2agu0kg2zlpkdckce865l3zps8mxjurxthfh3m7035qe5hh7f"}, + {Key: "success", Value: "true"}, + }, + }, + }, + }, + "contract returns err response": { + ibcPkg: anyContractIBCPkg, + contractRsp: channeltypes.NewErrorAcknowledgement(types.ErrInvalid.Wrap("testing")), + expAck: channeltypes.NewErrorAcknowledgement(types.ErrInvalid.Wrap("testing")), + expEvents: sdk.Events{ + { + Type: "ibc_packet_received", + Attributes: []abci.EventAttribute{ + {Key: "module", Value: "wasm"}, + {Key: "_contract_address", Value: "cosmos1w09vr7rpe2agu0kg2zlpkdckce865l3zps8mxjurxthfh3m7035qe5hh7f"}, + {Key: "success", Value: "false"}, + }, + }, + }, + }, + "nil considered success response": { // regression only + ibcPkg: anyContractIBCPkg, + expEvents: sdk.Events{ + myCustomEvent, + { + Type: "ibc_packet_received", + Attributes: []abci.EventAttribute{ + {Key: "module", Value: "wasm"}, + {Key: "_contract_address", Value: "cosmos1w09vr7rpe2agu0kg2zlpkdckce865l3zps8mxjurxthfh3m7035qe5hh7f"}, + {Key: "success", Value: "true"}, + }, + }, + }, + }, + "unknown contract port": { + ibcPkg: IBCPacketFixture(func(p *channeltypes.Packet) { + p.DestinationPort = "not-a-contract-port" + }), + expPanic: true, + }, + "contract executed with error": { + ibcPkg: anyContractIBCPkg, + contractErr: types.ErrInvalid.Wrap("testing"), + expAck: channeltypes.NewErrorAcknowledgement(types.ErrInvalid.Wrap("testing")), + expEvents: sdk.Events{{ + Type: "ibc_packet_received", + Attributes: []abci.EventAttribute{ + {Key: "module", Value: "wasm"}, + {Key: "_contract_address", Value: "cosmos1w09vr7rpe2agu0kg2zlpkdckce865l3zps8mxjurxthfh3m7035qe5hh7f"}, + {Key: "success", Value: "false"}, + {Key: "error", Value: "testing: invalid"}, // not redacted + }, + }}, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + mock := IBCContractKeeperMock{ + OnRecvPacketFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, msg wasmvmtypes.IBCPacketReceiveMsg) (ibcexported.Acknowledgement, error) { + // additional custom event to confirm event handling on state commit/ rollback + ctx.EventManager().EmitEvent(myCustomEvent) + return spec.contractRsp, spec.contractErr + }, + } + h := NewIBCHandler(mock, nil, nil) + em := &sdk.EventManager{} + ctx := sdk.Context{}.WithEventManager(em) + if spec.expPanic { + require.Panics(t, func() { + _ = h.OnRecvPacket(ctx, spec.ibcPkg, anyRelayerAddr) + }) + return + } + gotAck := h.OnRecvPacket(ctx, spec.ibcPkg, anyRelayerAddr) + assert.Equal(t, spec.expAck, gotAck) + assert.Equal(t, spec.expEvents, em.Events()) + }) + } +} + func TestMapToWasmVMIBCPacket(t *testing.T) { var myTimestamp uint64 = 1 specs := map[string]struct { @@ -80,3 +194,17 @@ func IBCPacketFixture(mutators ...func(p *channeltypes.Packet)) channeltypes.Pac } return r } + +var _ types.IBCContractKeeper = &IBCContractKeeperMock{} + +type IBCContractKeeperMock struct { + types.IBCContractKeeper + OnRecvPacketFn func(ctx sdk.Context, contractAddr sdk.AccAddress, msg wasmvmtypes.IBCPacketReceiveMsg) (ibcexported.Acknowledgement, error) +} + +func (m IBCContractKeeperMock) OnRecvPacket(ctx sdk.Context, contractAddr sdk.AccAddress, msg wasmvmtypes.IBCPacketReceiveMsg) (ibcexported.Acknowledgement, error) { + if m.OnRecvPacketFn == nil { + panic("not expected to be called") + } + return m.OnRecvPacketFn(ctx, contractAddr, msg) +} diff --git a/x/wasm/keeper/relay.go b/x/wasm/keeper/relay.go index fa1c4ac04f..af9989c683 100644 --- a/x/wasm/keeper/relay.go +++ b/x/wasm/keeper/relay.go @@ -3,6 +3,9 @@ package keeper import ( "time" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" + errorsmod "cosmossdk.io/errors" wasmvmtypes "github.com/CosmWasm/wasmvm/types" "github.com/cosmos/cosmos-sdk/telemetry" @@ -116,7 +119,7 @@ func (k Keeper) OnRecvPacket( ctx sdk.Context, contractAddr sdk.AccAddress, msg wasmvmtypes.IBCPacketReceiveMsg, -) ([]byte, error) { +) (ibcexported.Acknowledgement, error) { defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "ibc-recv-packet") contractInfo, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddr) if err != nil { @@ -130,13 +133,34 @@ func (k Keeper) OnRecvPacket( res, gasUsed, execErr := k.wasmVM.IBCPacketReceive(codeInfo.CodeHash, env, msg, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas, costJSONDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { - panic(execErr) + panic(execErr) // let contract fully abort IBC receive in certain case } - if res.Err != "" { // handle error case as before https://github.com/CosmWasm/wasmvm/commit/c300106fe5c9426a495f8e10821e00a9330c56c6 - return nil, errorsmod.Wrap(types.ErrExecuteFailed, res.Err) + if res.Err != "" { + // return error ACK with non-redacted contract message, state will be reverted + return channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Error{Error: res.Err}, + }, nil } // note submessage reply results can overwrite the `Acknowledgement` data - return k.handleContractResponse(ctx, contractAddr, contractInfo.IBCPortID, res.Ok.Messages, res.Ok.Attributes, res.Ok.Acknowledgement, res.Ok.Events) + data, err := k.handleContractResponse(ctx, contractAddr, contractInfo.IBCPortID, res.Ok.Messages, res.Ok.Attributes, res.Ok.Acknowledgement, res.Ok.Events) + if err != nil { + // submessage errors result in error ACK with state reverted. Error message is redacted + return nil, err + } + // success ACK, state will be committed + return ContractConfirmStateAck(data), nil +} + +var _ ibcexported.Acknowledgement = ContractConfirmStateAck{} + +type ContractConfirmStateAck []byte + +func (w ContractConfirmStateAck) Success() bool { + return true // always commit state +} + +func (w ContractConfirmStateAck) Acknowledgement() []byte { + return w } // OnAckPacket calls the contract to handle the "acknowledgement" data which can contain success or failure of a packet diff --git a/x/wasm/keeper/relay_test.go b/x/wasm/keeper/relay_test.go index 9fb377a09c..abb8e4b4c5 100644 --- a/x/wasm/keeper/relay_test.go +++ b/x/wasm/keeper/relay_test.go @@ -319,7 +319,7 @@ func TestOnRecvPacket(t *testing.T) { specs := map[string]struct { contractAddr sdk.AccAddress - contractResp *wasmvmtypes.IBCReceiveResponse + contractResp *wasmvmtypes.IBCReceiveResult contractErr error overwriteMessenger *wasmtesting.MockMessageHandler mockReplyFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) @@ -329,26 +329,38 @@ func TestOnRecvPacket(t *testing.T) { expPanic bool expEventTypes []string }{ - "consume contract gas": { + "contract returns success ack": { contractAddr: example.Contract, expContractGas: myContractGas, - contractResp: &wasmvmtypes.IBCReceiveResponse{ - Acknowledgement: []byte("myAck"), + contractResp: &wasmvmtypes.IBCReceiveResult{ + Ok: &wasmvmtypes.IBCReceiveResponse{Acknowledgement: []byte("myAck")}, }, expAck: []byte("myAck"), }, - "can return empty ack": { + "can return empty ack data": { contractAddr: example.Contract, expContractGas: myContractGas, - contractResp: &wasmvmtypes.IBCReceiveResponse{}, + contractResp: &wasmvmtypes.IBCReceiveResult{ + Ok: &wasmvmtypes.IBCReceiveResponse{}, + }, }, - "consume gas on error, ignore events + messages": { + "contract Err result converted to error Ack": { + contractAddr: example.Contract, + expContractGas: myContractGas, + contractResp: &wasmvmtypes.IBCReceiveResult{ + Err: "my-error", + }, + expAck: []byte(`{"error":"my-error"}`), // without error msg redaction + }, + "contract aborts tx with error": { contractAddr: example.Contract, expContractGas: myContractGas, - contractResp: &wasmvmtypes.IBCReceiveResponse{ - Acknowledgement: []byte("myAck"), - Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}}, - Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, + contractResp: &wasmvmtypes.IBCReceiveResult{ + Ok: &wasmvmtypes.IBCReceiveResponse{ + Acknowledgement: []byte("myAck"), + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}}, + Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, + }, }, contractErr: errors.New("test, ignore"), expPanic: true, @@ -356,18 +368,22 @@ func TestOnRecvPacket(t *testing.T) { "dispatch contract messages on success": { contractAddr: example.Contract, expContractGas: myContractGas, - contractResp: &wasmvmtypes.IBCReceiveResponse{ - Acknowledgement: []byte("myAck"), - Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, + contractResp: &wasmvmtypes.IBCReceiveResult{ + Ok: &wasmvmtypes.IBCReceiveResponse{ + Acknowledgement: []byte("myAck"), + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, + }, }, expAck: []byte("myAck"), }, "emit contract attributes on success": { contractAddr: example.Contract, expContractGas: myContractGas + 10, - contractResp: &wasmvmtypes.IBCReceiveResponse{ - Acknowledgement: []byte("myAck"), - Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, + contractResp: &wasmvmtypes.IBCReceiveResult{ + Ok: &wasmvmtypes.IBCReceiveResponse{ + Acknowledgement: []byte("myAck"), + Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, + }, }, expEventTypes: []string{types.WasmModuleEventType}, expAck: []byte("myAck"), @@ -375,27 +391,31 @@ func TestOnRecvPacket(t *testing.T) { "emit contract events on success": { contractAddr: example.Contract, expContractGas: myContractGas + 46, // charge or custom event as well - contractResp: &wasmvmtypes.IBCReceiveResponse{ - Acknowledgement: []byte("myAck"), - Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, - Events: []wasmvmtypes.Event{{ - Type: "custom", - Attributes: []wasmvmtypes.EventAttribute{{ - Key: "message", - Value: "to rudi", + contractResp: &wasmvmtypes.IBCReceiveResult{ + Ok: &wasmvmtypes.IBCReceiveResponse{ + Acknowledgement: []byte("myAck"), + Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, + Events: []wasmvmtypes.Event{{ + Type: "custom", + Attributes: []wasmvmtypes.EventAttribute{{ + Key: "message", + Value: "to rudi", + }}, }}, - }}, + }, }, expEventTypes: []string{types.WasmModuleEventType, "wasm-custom"}, expAck: []byte("myAck"), }, - "messenger errors returned, events stored": { + "messenger errors returned": { contractAddr: example.Contract, expContractGas: myContractGas + 10, - contractResp: &wasmvmtypes.IBCReceiveResponse{ - Acknowledgement: []byte("myAck"), - Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, - Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, + contractResp: &wasmvmtypes.IBCReceiveResult{ + Ok: &wasmvmtypes.IBCReceiveResponse{ + Acknowledgement: []byte("myAck"), + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, + Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, + }, }, overwriteMessenger: wasmtesting.NewErroringMessageHandler(), expErr: true, @@ -404,9 +424,11 @@ func TestOnRecvPacket(t *testing.T) { "submessage reply can overwrite ack data": { contractAddr: example.Contract, expContractGas: myContractGas + storageCosts, - contractResp: &wasmvmtypes.IBCReceiveResponse{ - Acknowledgement: []byte("myAck"), - Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyAlways, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}}, + contractResp: &wasmvmtypes.IBCReceiveResult{ + Ok: &wasmvmtypes.IBCReceiveResponse{ + Acknowledgement: []byte("myAck"), + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyAlways, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}}, + }, }, mockReplyFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { return &wasmvmtypes.Response{Data: []byte("myBetterAck")}, 0, nil @@ -425,7 +447,7 @@ func TestOnRecvPacket(t *testing.T) { m.IBCPacketReceiveFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResult, uint64, error) { assert.Equal(t, myPacket, msg.Packet) - return &wasmvmtypes.IBCReceiveResult{Ok: spec.contractResp}, myContractGas * DefaultGasMultiplier, spec.contractErr + return spec.contractResp, myContractGas * DefaultGasMultiplier, spec.contractErr } if spec.mockReplyFn != nil { m.ReplyFn = spec.mockReplyFn @@ -462,17 +484,23 @@ func TestOnRecvPacket(t *testing.T) { return } require.NoError(t, err) - require.Equal(t, spec.expAck, gotAck) + require.Equal(t, spec.expAck, gotAck.Acknowledgement()) // verify gas consumed const storageCosts = sdk.Gas(2903) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) - // verify msgs dispatched - require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) - for i, m := range spec.contractResp.Messages { - assert.Equal(t, (*capturedMsgs)[i], m.Msg) + + // verify msgs dispatched on success/ err response + if spec.contractResp.Err != "" { + assert.Empty(t, capturedMsgs) // no messages captured on err response + assert.Equal(t, spec.expEventTypes, stripTypes(ctx.EventManager().Events())) + } else { + require.Len(t, *capturedMsgs, len(spec.contractResp.Ok.Messages)) + for i, m := range spec.contractResp.Ok.Messages { + assert.Equal(t, (*capturedMsgs)[i], m.Msg) + } + assert.Equal(t, spec.expEventTypes, stripTypes(ctx.EventManager().Events())) } - assert.Equal(t, spec.expEventTypes, stripTypes(ctx.EventManager().Events())) }) } } diff --git a/x/wasm/types/events.go b/x/wasm/types/events.go index 442c3ed369..7034b37b76 100644 --- a/x/wasm/types/events.go +++ b/x/wasm/types/events.go @@ -1,5 +1,12 @@ package types +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/ibc-go/v7/modules/core/exported" +) + const ( // WasmModuleEventType is stored with any contract TX that returns non empty EventAttributes WasmModuleEventType = "wasm" @@ -17,8 +24,32 @@ const ( EventTypeGovContractResult = "gov_contract_result" EventTypeUpdateContractAdmin = "update_contract_admin" EventTypeUpdateCodeAccessConfig = "update_code_access_config" + EventTypePacketRecv = "ibc_packet_received" + // add new types to IsAcceptedEventOnRecvPacketErrorAck ) +// EmitAcknowledgementEvent emits an event signalling a successful or failed acknowledgement and including the error +// details if any. +func EmitAcknowledgementEvent(ctx sdk.Context, contractAddr sdk.AccAddress, ack exported.Acknowledgement, err error) { + success := err == nil && (ack == nil || ack.Success()) + attributes := []sdk.Attribute{ + sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), + sdk.NewAttribute(AttributeKeyContractAddr, contractAddr.String()), + sdk.NewAttribute(AttributeKeyAckSuccess, fmt.Sprintf("%t", success)), + } + + if err != nil { + attributes = append(attributes, sdk.NewAttribute(AttributeKeyAckError, err.Error())) + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + EventTypePacketRecv, + attributes..., + ), + ) +} + // event attributes returned from contract execution const ( AttributeReservedPrefix = "_" @@ -31,4 +62,6 @@ const ( AttributeKeyNewAdmin = "new_admin_address" AttributeKeyCodePermission = "code_permission" AttributeKeyAuthorizedAddresses = "authorized_addresses" + AttributeKeyAckSuccess = "success" + AttributeKeyAckError = "error" ) diff --git a/x/wasm/types/exported_keepers.go b/x/wasm/types/exported_keepers.go index dcf97cb2cc..4fa5c6ac59 100644 --- a/x/wasm/types/exported_keepers.go +++ b/x/wasm/types/exported_keepers.go @@ -4,6 +4,7 @@ import ( wasmvmtypes "github.com/CosmWasm/wasmvm/types" sdk "github.com/cosmos/cosmos-sdk/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" ) // ViewKeeper provides read only operations @@ -100,7 +101,7 @@ type IBCContractKeeper interface { ctx sdk.Context, contractAddr sdk.AccAddress, msg wasmvmtypes.IBCPacketReceiveMsg, - ) ([]byte, error) + ) (ibcexported.Acknowledgement, error) OnAckPacket( ctx sdk.Context, contractAddr sdk.AccAddress,