diff --git a/chain/cosmos/chain_node.go b/chain/cosmos/chain_node.go index 4b21d06c6..dca954628 100644 --- a/chain/cosmos/chain_node.go +++ b/chain/cosmos/chain_node.go @@ -814,7 +814,7 @@ func (tn *ChainNode) StoreContract(ctx context.Context, keyName string, fileName return res.CodeInfos[0].CodeID, nil } -func (tn *ChainNode) getTransaction(clientCtx client.Context, txHash string) (*types.TxResponse, error) { +func (tn *ChainNode) GetTransaction(clientCtx client.Context, txHash string) (*types.TxResponse, error) { // Retry because sometimes the tx is not committed to state yet. var txResp *types.TxResponse err := retry.Do(func() error { @@ -938,7 +938,7 @@ func (tn *ChainNode) InstantiateContract(ctx context.Context, keyName string, co return "", err } - txResp, err := tn.getTransaction(tn.CliContext(), txHash) + txResp, err := tn.GetTransaction(tn.CliContext(), txHash) if err != nil { return "", fmt.Errorf("failed to get transaction %s: %w", txHash, err) } @@ -961,11 +961,25 @@ func (tn *ChainNode) InstantiateContract(ctx context.Context, keyName string, co } // ExecuteContract executes a contract transaction with a message using it's address. -func (tn *ChainNode) ExecuteContract(ctx context.Context, keyName string, contractAddress string, message string, extraExecTxArgs ...string) (txHash string, err error) { +func (tn *ChainNode) ExecuteContract(ctx context.Context, keyName string, contractAddress string, message string, extraExecTxArgs ...string) (res *types.TxResponse, err error) { cmd := []string{"wasm", "execute", contractAddress, message} cmd = append(cmd, extraExecTxArgs...) - return tn.ExecTx(ctx, keyName, cmd...) + txHash, err := tn.ExecTx(ctx, keyName, cmd...) + if err != nil { + return &types.TxResponse{}, err + } + + txResp, err := tn.GetTransaction(tn.CliContext(), txHash) + if err != nil { + return &types.TxResponse{}, fmt.Errorf("failed to get transaction %s: %w", txHash, err) + } + + if txResp.Code != 0 { + return txResp, fmt.Errorf("error in transaction (code: %d): %s", txResp.Code, txResp.RawLog) + } + + return txResp, nil } // QueryContract performs a smart query, taking in a query struct and returning a error with the response struct populated. diff --git a/examples/cosmos/chain_miscellaneous_test.go b/examples/cosmos/chain_miscellaneous_test.go index 11dbd8b85..bc14e0d41 100644 --- a/examples/cosmos/chain_miscellaneous_test.go +++ b/examples/cosmos/chain_miscellaneous_test.go @@ -7,9 +7,11 @@ import ( "cosmossdk.io/math" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" sdk "github.com/cosmos/cosmos-sdk/types" + testutil "github.com/cosmos/cosmos-sdk/types/module/testutil" "github.com/strangelove-ventures/interchaintest/v8" "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v8/ibc" @@ -44,10 +46,11 @@ func CosmosChainTestMiscellaneous(t *testing.T, name, version string) { ChainName: name, Version: version, ChainConfig: ibc.ChainConfig{ - Denom: "ujuno", - Bech32Prefix: "juno", - CoinType: "118", - ModifyGenesis: cosmos.ModifyGenesis(sdk47Genesis), + Denom: "ujuno", + Bech32Prefix: "juno", + CoinType: "118", + ModifyGenesis: cosmos.ModifyGenesis(sdk47Genesis), + EncodingConfig: wasmEncoding(), }, NumValidators: &numVals, NumFullNodes: &numFullNodes, @@ -87,10 +90,17 @@ func CosmosChainTestMiscellaneous(t *testing.T, name, version string) { testQueryCmd(ctx, t, chain) testHasCommand(ctx, t, chain) testTokenFactory(ctx, t, chain, users) + testFailedCWExecute(ctx, t, chain, users) testAddingNode(ctx, t, chain) testGetGovernanceAddress(ctx, t, chain) } +func wasmEncoding() *testutil.TestEncodingConfig { + cfg := cosmos.DefaultEncoding() + wasmtypes.RegisterInterfaces(cfg.InterfaceRegistry) + return &cfg +} + func testBuildDependencies(ctx context.Context, t *testing.T, chain *cosmos.CosmosChain) { deps := chain.Validators[0].GetBuildInformation(ctx) @@ -129,6 +139,28 @@ func testBuildDependencies(ctx context.Context, t *testing.T, chain *cosmos.Cosm } } +func testFailedCWExecute(ctx context.Context, t *testing.T, chain *cosmos.CosmosChain, users []ibc.Wallet) { + user := users[0] + keyName := user.KeyName() + + codeId, err := chain.StoreContract(ctx, keyName, "sample_contracts/cw_template.wasm") + if err != nil { + t.Fatal(err) + } + + contractAddr, err := chain.InstantiateContract(ctx, keyName, codeId, `{"count":0}`, true) + if err != nil { + t.Fatal(err) + } + + // execute on the contract with the wrong message (err) + txResp, err := chain.ExecuteContract(ctx, keyName, contractAddr, `{"not_a_func":{}}`) + require.Error(t, err) + fmt.Printf("txResp.RawLog: %+v\n", txResp.RawLog) + fmt.Printf("err: %+v\n", err) + require.Contains(t, err.Error(), "failed to execute message") +} + func testWalletKeys(ctx context.Context, t *testing.T, chain *cosmos.CosmosChain) { // create a general key randKey := "randkey123" diff --git a/examples/cosmos/sample_contracts/cw_template.wasm b/examples/cosmos/sample_contracts/cw_template.wasm new file mode 100644 index 000000000..909cbdd19 Binary files /dev/null and b/examples/cosmos/sample_contracts/cw_template.wasm differ diff --git a/examples/ibc/wasm/wasm_icq_test.go b/examples/ibc/wasm/wasm_icq_test.go index a6fd3ab71..22c0b8301 100644 --- a/examples/ibc/wasm/wasm_icq_test.go +++ b/examples/ibc/wasm/wasm_icq_test.go @@ -278,19 +278,9 @@ func TestInterchainQueriesWASM(t *testing.T) { logger.Info("Executing msg ->", zap.String("msg", msg)) //Query the contract on chain 1. The contract makes an interchain query to chain 2 to get the chain 2 user's balance. - hash, err := chain1CChain.ExecuteContract(ctx, chain1User.KeyName(), contractAddr, msg) - - require.NoError(t, err) - - // Check the results from the interchain query above. - cmd = []string{chain1.Config().Bin, "query", "tx", hash, - "--node", chain1.GetRPCAddress(), - "--home", chain1.HomeDir(), - "--chain-id", chain1.Config().ChainID, - "--output", "json", - } - _, _, err = chain1.Exec(ctx, cmd, nil) + resp, err := chain1CChain.ExecuteContract(ctx, chain1User.KeyName(), contractAddr, msg) require.NoError(t, err) + require.NotNil(t, resp) // Wait a few blocks for query to be sent to counterparty. err = testutil.WaitForBlocks(ctx, 5, chain1, chain2)