diff --git a/tests/e2e/group_test.go b/tests/e2e/group_test.go index 9852d9793a..2cda127a74 100644 --- a/tests/e2e/group_test.go +++ b/tests/e2e/group_test.go @@ -27,7 +27,7 @@ func TestGroupWithContract(t *testing.T) { coord := ibctesting.NewCoordinator(t, 1) chain := coord.GetChain(ibctesting.GetChainID(1)) - contractAddr := e2e.InstantiateReflectContract(t, chain) + contractAddr := e2e.InstantiateStargateReflectContract(t, chain) chain.Fund(contractAddr, sdkmath.NewIntFromUint64(1_000_000_000)) members := []group.MemberRequest{ @@ -74,3 +74,58 @@ func TestGroupWithContract(t *testing.T) { expBalanceAmount := sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.OneInt()) assert.Equal(t, expBalanceAmount.String(), recipientBalance.String()) } + +func TestGroupWithNewReflectContract(t *testing.T) { + // Given a group with a contract as only member + // When contract submits a proposal with try_execute + // Then the payload msg is executed + + coord := ibctesting.NewCoordinator(t, 1) + chain := coord.GetChain(ibctesting.GetChainID(1)) + contractAddr := e2e.InstantiateReflectContract(t, chain) + chain.Fund(contractAddr, sdkmath.NewIntFromUint64(1_000_000_000)) + + members := []group.MemberRequest{ + { + Address: contractAddr.String(), + Weight: "1", + Metadata: "my contract", + }, + } + msg, err := group.NewMsgCreateGroupWithPolicy( + chain.SenderAccount.GetAddress().String(), + members, + "my group", + "my metadata", + false, + group.NewPercentageDecisionPolicy("1", time.Second, 0), + ) + require.NoError(t, err) + rsp, err := chain.SendMsgs(msg) + require.NoError(t, err) + + var createRsp group.MsgCreateGroupWithPolicyResponse + chain.UnwrapExecTXResult(rsp, &createRsp) + groupID, policyAddr := createRsp.GroupId, sdk.MustAccAddressFromBech32(createRsp.GroupPolicyAddress) + require.NotEmpty(t, groupID) + chain.Fund(policyAddr, sdkmath.NewIntFromUint64(1_000_000_000)) + // and a proposal submitted + recipientAddr := sdk.AccAddress(rand.Bytes(address.Len)) + + payload := []sdk.Msg{banktypes.NewMsgSend(policyAddr, recipientAddr, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.OneInt())))} + propMsg, err := group.NewMsgSubmitProposal(policyAddr.String(), []string{contractAddr.String()}, payload, "my proposal", group.Exec_EXEC_TRY, "my title", "my description") + require.NoError(t, err) + + rsp = e2e.MustExecViaAnyReflectContract(t, chain, contractAddr, propMsg) + var execRsp types.MsgExecuteContractResponse + chain.UnwrapExecTXResult(rsp, &execRsp) + + var groupRsp group.MsgSubmitProposalResponse + require.NoError(t, chain.Codec.Unmarshal(execRsp.Data, &groupRsp)) + // require.NotEmpty(t, groupRsp.ProposalId) + + // and coins received + recipientBalance := chain.Balance(recipientAddr, sdk.DefaultBondDenom) + expBalanceAmount := sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.OneInt()) + assert.Equal(t, expBalanceAmount.String(), recipientBalance.String()) +} diff --git a/tests/e2e/reflect_helper.go b/tests/e2e/reflect_helper.go index e64d8bf139..44235eab3b 100644 --- a/tests/e2e/reflect_helper.go +++ b/tests/e2e/reflect_helper.go @@ -1,7 +1,9 @@ package e2e import ( + "encoding/base64" "encoding/json" + "fmt" "testing" wasmvmtypes "github.com/CosmWasm/wasmvm/v2/types" @@ -16,9 +18,18 @@ import ( "github.com/CosmWasm/wasmd/x/wasm/types" ) -// InstantiateReflectContract store and instantiate a reflect contract instance +// InstantiateStargateReflectContract stores and instantiates a pre 2.0 reflect contract instance. +// This instance still expects the old CosmosMsg.Stargate variant instead of the new CosmosMsg.Any. +func InstantiateStargateReflectContract(t *testing.T, chain *ibctesting.TestChain) sdk.AccAddress { + codeID := chain.StoreCodeFile("../../x/wasm/keeper/testdata/reflect.wasm").CodeID + contractAddr := chain.InstantiateContract(codeID, []byte(`{}`)) + require.NotEmpty(t, contractAddr) + return contractAddr +} + +// InstantiateReflectContract stores and instantiates a 2.0 reflect contract instance. func InstantiateReflectContract(t *testing.T, chain *ibctesting.TestChain) sdk.AccAddress { - codeID := chain.StoreCodeFile("../../x/wasm/keeper/testdata/reflect_1_1.wasm").CodeID + codeID := chain.StoreCodeFile("../../x/wasm/keeper/testdata/reflect_2_0.wasm").CodeID contractAddr := chain.InstantiateContract(codeID, []byte(`{}`)) require.NotEmpty(t, contractAddr) return contractAddr @@ -37,6 +48,32 @@ type sdkMessageType interface { } func MustExecViaStargateReflectContract[T sdkMessageType](t *testing.T, chain *ibctesting.TestChain, contractAddr sdk.AccAddress, msgs ...T) *abci.ExecTxResult { + require.NotEmpty(t, msgs) + // convert messages to stargate variant + vmMsgs := make([]string, len(msgs)) + for i, m := range msgs { + bz, err := chain.Codec.Marshal(m) + require.NoError(t, err) + // json is built manually because the wasmvm CosmosMsg does not have the `Stargate` variant anymore + vmMsgs[i] = fmt.Sprintf("{\"stargate\":{\"type_url\":\"%s\",\"value\":\"%s\"}}", sdk.MsgTypeURL(m), base64.StdEncoding.EncodeToString(bz)) + } + // build the complete reflect message + reflectSendBz := []byte(fmt.Sprintf("{\"reflect_msg\":{\"msgs\":%s}}", vmMsgs)) + + // {"reflect_msg":{"msgs":[{"stargate":{"type_url":"mytype","value":"EjQ="}}]}} + + t.Log(string(reflectSendBz)) + execMsg := &types.MsgExecuteContract{ + Sender: chain.SenderAccount.GetAddress().String(), + Contract: contractAddr.String(), + Msg: reflectSendBz, + } + rsp, err := chain.SendMsgs(execMsg) + require.NoError(t, err) + return rsp +} + +func MustExecViaAnyReflectContract[T sdkMessageType](t *testing.T, chain *ibctesting.TestChain, contractAddr sdk.AccAddress, msgs ...T) *abci.ExecTxResult { vmMsgs := make([]wasmvmtypes.CosmosMsg, len(msgs)) for i, m := range msgs { bz, err := chain.Codec.Marshal(m) diff --git a/x/wasm/keeper/keeper_test.go b/x/wasm/keeper/keeper_test.go index cb7d11be10..d39554ff48 100644 --- a/x/wasm/keeper/keeper_test.go +++ b/x/wasm/keeper/keeper_test.go @@ -44,7 +44,7 @@ import ( var hackatomWasm []byte var AvailableCapabilities = []string{ - "iterator", "staking", "stargate", "cosmwasm_1_1", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4", + "iterator", "staking", "stargate", "cosmwasm_1_1", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4", "cosmwasm_2_0", } func TestNewKeeper(t *testing.T) { @@ -421,7 +421,7 @@ func TestInstantiate(t *testing.T) { gasAfter := ctx.GasMeter().GasConsumed() if types.EnableGasVerification { - require.Equal(t, uint64(0x1bc64), gasAfter-gasBefore) + require.Equal(t, uint64(0x1bc5a), gasAfter-gasBefore) } // ensure it is stored properly @@ -2459,13 +2459,13 @@ func TestGasConsumed(t *testing.T) { originalMeter: storetypes.NewGasMeter(100), gasRegister: types.NewWasmGasRegister(types.DefaultGasRegisterConfig()), consumeGas: storetypes.Gas(1), - expMultipliedGasConsumed: 140000000, + expMultipliedGasConsumed: 140000, }, "consumeGas = limit": { originalMeter: storetypes.NewGasMeter(1), gasRegister: types.NewWasmGasRegister(types.DefaultGasRegisterConfig()), consumeGas: storetypes.Gas(1), - expMultipliedGasConsumed: 140000000, + expMultipliedGasConsumed: 140000, }, "consumeGas > limit": { originalMeter: storetypes.NewGasMeter(10), diff --git a/x/wasm/keeper/query_plugin_integration_test.go b/x/wasm/keeper/query_plugin_integration_test.go index 5615e835f6..4ff5954c82 100644 --- a/x/wasm/keeper/query_plugin_integration_test.go +++ b/x/wasm/keeper/query_plugin_integration_test.go @@ -794,7 +794,7 @@ func TestIBCListChannelsQuery(t *testing.T) { query: &wasmvmtypes.IBCQuery{ListChannels: &wasmvmtypes.ListChannelsQuery{}}, assert: func(t *testing.T, d []byte) { rsp := unmarshalReflect[wasmvmtypes.ListChannelsResponse](t, d) - assert.Nil(t, rsp.Channels) + assert.Empty(t, rsp.Channels) }, }, "no matching channels": { diff --git a/x/wasm/keeper/reflect_test.go b/x/wasm/keeper/reflect_test.go index 24581f2806..edb338b918 100644 --- a/x/wasm/keeper/reflect_test.go +++ b/x/wasm/keeper/reflect_test.go @@ -25,7 +25,7 @@ import ( var ( CyberpunkCapabilities = []string{"staking", "mask", "stargate", "cosmwasm_1_1", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4"} - ReflectCapabilities = CyberpunkCapabilities + ReflectCapabilities = []string{"staking", "mask", "stargate", "cosmwasm_1_1", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4", "cosmwasm_2_0"} ) func mustUnmarshal(t *testing.T, data []byte, res interface{}) { diff --git a/x/wasm/keeper/testdata/contracts.go b/x/wasm/keeper/testdata/contracts.go index fe587a091d..eb63bdeef6 100644 --- a/x/wasm/keeper/testdata/contracts.go +++ b/x/wasm/keeper/testdata/contracts.go @@ -13,7 +13,7 @@ const ( ) var ( - //go:embed reflect.wasm + //go:embed reflect_2_0.wasm reflectContract []byte //go:embed reflect_1_1.wasm migrateReflectContract []byte diff --git a/x/wasm/keeper/testdata/reflect_2_0.wasm b/x/wasm/keeper/testdata/reflect_2_0.wasm new file mode 100644 index 0000000000..9791208ace Binary files /dev/null and b/x/wasm/keeper/testdata/reflect_2_0.wasm differ diff --git a/x/wasm/module_test.go b/x/wasm/module_test.go index 63e8f5cd90..d75838a2a5 100644 --- a/x/wasm/module_test.go +++ b/x/wasm/module_test.go @@ -63,7 +63,7 @@ func setupTest(t *testing.T) testData { InstantiateDefaultPermission: v2.AccessTypeEverybody, } - ctx, keepers := keeper.CreateTestInput(t, false, []string{"iterator", "staking", "stargate", "cosmwasm_1_1", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4"}) + ctx, keepers := keeper.CreateTestInput(t, false, []string{"iterator", "staking", "stargate", "cosmwasm_1_1", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4", "cosmwasm_2_0"}) encConf := keeper.MakeEncodingConfig(t) queryRouter := baseapp.NewGRPCQueryRouter() serviceRouter := baseapp.NewMsgServiceRouter()