From 98580347b78085d0c4b2fe2afa7f57ee91d60e7c Mon Sep 17 00:00:00 2001 From: GNaD13 <89174180+GNaD13@users.noreply.github.com> Date: Tue, 18 Oct 2022 22:36:13 +0700 Subject: [PATCH] Add test for contract (#1053) * add test close IBC different contract ibc channel * fix test send ibc diff channel contract handle * remove unused comment * remove expose func HandleContractResponse * correct comment for test scenario * fix nit --- x/wasm/ibctesting/chain.go | 35 ++++++++++++++ x/wasm/relay_test.go | 97 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) diff --git a/x/wasm/ibctesting/chain.go b/x/wasm/ibctesting/chain.go index c2f6f142..8d0adfb7 100644 --- a/x/wasm/ibctesting/chain.go +++ b/x/wasm/ibctesting/chain.go @@ -273,6 +273,41 @@ func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) (*sdk.Result, error) { return r, nil } +func (chain *TestChain) SendMsgsExpPass(expPass bool, msgs ...sdk.Msg) (*sdk.Result, error) { + // ensure the chain has the latest time + chain.Coordinator.UpdateTimeForChain(chain) + + _, r, err := app.SignAndDeliver( + chain.t, + chain.TxConfig, + chain.App.BaseApp, + chain.GetContext().BlockHeader(), + msgs, + chain.ChainID, + []uint64{chain.SenderAccount.GetAccountNumber()}, + []uint64{chain.SenderAccount.GetSequence()}, + true, expPass, chain.SenderPrivKey, + ) + if err != nil { + return nil, err + } + + // SignAndDeliver calls app.Commit() + chain.NextBlock() + + // increment sequence for successful transaction execution + err = chain.SenderAccount.SetSequence(chain.SenderAccount.GetSequence() + 1) + if err != nil { + return nil, err + } + + chain.Coordinator.IncrementTime() + + chain.captureIBCEvents(r) + + return r, nil +} + func (chain *TestChain) captureIBCEvents(r *sdk.Result) { toSend := getSendPackets(r.Events) if len(toSend) > 0 { diff --git a/x/wasm/relay_test.go b/x/wasm/relay_test.go index 63e4bdc4..c1cff76c 100644 --- a/x/wasm/relay_test.go +++ b/x/wasm/relay_test.go @@ -399,6 +399,66 @@ func TestContractHandlesChannelClose(t *testing.T) { assert.True(t, myContractB.closeCalled) } +func TestContractHandlesChannelCloseNotOwned(t *testing.T) { + // scenario: given two chains, + // with a contract A1, A2 on chain A, contract B on chain B + // contract A2 try to close ibc channel that create between A1 and B + + myContractA1 := &closeChannelContract{} + myContractA2 := &closeChannelContract{} + myContractB := &closeChannelContract{} + + var ( + chainAOpts = []wasmkeeper.Option{ + wasmkeeper.WithWasmEngine( + wasmtesting.NewIBCContractMockWasmer(myContractA1)), + wasmkeeper.WithWasmEngine( + wasmtesting.NewIBCContractMockWasmer(myContractA2)), + } + chainBOpts = []wasmkeeper.Option{ + wasmkeeper.WithWasmEngine( + wasmtesting.NewIBCContractMockWasmer(myContractB)), + } + coordinator = wasmibctesting.NewCoordinator(t, 2, chainAOpts, chainBOpts) + + chainA = coordinator.GetChain(wasmibctesting.GetChainID(0)) + chainB = coordinator.GetChain(wasmibctesting.GetChainID(1)) + ) + + coordinator.CommitBlock(chainA, chainB) + myContractAddrA1 := chainA.SeedNewContractInstance() + myContractAddrA2 := chainA.SeedNewContractInstance() + _ = chainB.SeedNewContractInstance() // skip one instance + _ = chainB.SeedNewContractInstance() // skip one instance + myContractAddrB := chainB.SeedNewContractInstance() + + path := wasmibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig = &ibctesting.ChannelConfig{ + PortID: chainA.ContractInfo(myContractAddrA1).IBCPortID, + Version: ibctransfertypes.Version, + Order: channeltypes.UNORDERED, + } + path.EndpointB.ChannelConfig = &ibctesting.ChannelConfig{ + PortID: chainB.ContractInfo(myContractAddrB).IBCPortID, + Version: ibctransfertypes.Version, + Order: channeltypes.UNORDERED, + } + coordinator.SetupConnections(path) + coordinator.CreateChannels(path) + + closeIBCChannelMsg := &types.MsgExecuteContract{ + Sender: chainA.SenderAccount.GetAddress().String(), + Contract: myContractAddrA2.String(), + Msg: closeIBCChannel{ + ChannelID: path.EndpointA.ChannelID, + }.GetBytes(), + Funds: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), + } + + _, err := chainA.SendMsgsExpPass(false, closeIBCChannelMsg) + require.Error(t, err) +} + var _ wasmtesting.IBCContractCallbacks = &captureCloseContract{} // contract that sets a flag on IBC channel close only. @@ -497,6 +557,43 @@ func (c *sendEmulatedIBCTransferContract) IBCPacketTimeout(codeID wasmvm.Checksu return &wasmvmtypes.IBCBasicResponse{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: returnTokens}}}}, 0, nil } +var _ wasmtesting.IBCContractCallbacks = &closeChannelContract{} + +type closeChannelContract struct { + contractStub + t *testing.T +} + +func (c *closeChannelContract) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + return &wasmvmtypes.IBCBasicResponse{}, 1, nil +} + +func (s *closeChannelContract) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { + var in closeIBCChannel + if err := json.Unmarshal(executeMsg, &in); err != nil { + return nil, 0, err + } + ibcMsg := &wasmvmtypes.IBCMsg{ + CloseChannel: &wasmvmtypes.CloseChannelMsg{ + ChannelID: in.ChannelID, + }, + } + + return &wasmvmtypes.Response{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{IBC: ibcMsg}}}}, 0, nil +} + +type closeIBCChannel struct { + ChannelID string +} + +func (g closeIBCChannel) GetBytes() types.RawContractMessage { + b, err := json.Marshal(g) + if err != nil { + panic(err) + } + return b +} + // custom contract execute payload type startTransfer struct { ChannelID string