From 0d692d6be5da6dff658553f0e371aa9a9829d32b Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 12 Jul 2022 16:02:56 +0300 Subject: [PATCH 01/16] TestBankMsgSend for v1 & v0.10 --- x/compute/internal/keeper/keeper_test.go | 4 +- .../internal/keeper/secret_contracts_test.go | 141 +++++++++++++++--- x/compute/internal/keeper/test_common.go | 3 +- .../testdata/test-contract/src/contract.rs | 25 ++++ .../v1-sanity-contract/src/contract.rs | 12 ++ .../testdata/v1-sanity-contract/src/msg.rs | 12 +- 6 files changed, 169 insertions(+), 28 deletions(-) diff --git a/x/compute/internal/keeper/keeper_test.go b/x/compute/internal/keeper/keeper_test.go index e13a51584..63cfd768e 100644 --- a/x/compute/internal/keeper/keeper_test.go +++ b/x/compute/internal/keeper/keeper_test.go @@ -443,7 +443,7 @@ func TestInstantiateWithDeposit(t *testing.T) { } // when - addr, _, err := initHelperImpl(t, keeper, ctx, codeID, bob, bobPriv, string(initMsgBz), false, false, defaultGasForTests, wasmCalls, int64(deposit)) + addr, _, err := initHelperImpl(t, keeper, ctx, codeID, bob, bobPriv, string(initMsgBz), false, false, defaultGasForTests, wasmCalls, sdk.NewCoins(sdk.NewInt64Coin("denom", int64(deposit)))) // then if spec.expError { require.Error(t, err) @@ -734,7 +734,7 @@ func TestExecuteWithDeposit(t *testing.T) { initMsgBz, err := json.Marshal(InitMsg{Verifier: bob, Beneficiary: fred}) require.NoError(t, err) - contractAddr, _, err := initHelperImpl(t, keeper, ctx, codeID, bob, bobPriv, string(initMsgBz), true, false, defaultGasForTests, -1, 0) + contractAddr, _, err := initHelperImpl(t, keeper, ctx, codeID, bob, bobPriv, string(initMsgBz), true, false, defaultGasForTests, -1, sdk.NewCoins()) require.Empty(t, err) wasmCalls := int64(-1) diff --git a/x/compute/internal/keeper/secret_contracts_test.go b/x/compute/internal/keeper/secret_contracts_test.go index 1bb760e00..b97ec9f7b 100644 --- a/x/compute/internal/keeper/secret_contracts_test.go +++ b/x/compute/internal/keeper/secret_contracts_test.go @@ -80,10 +80,8 @@ func setupTest(t *testing.T, wasmPath string) (sdk.Context, Keeper, uint64, stri ctx, keepers := CreateTestInput(t, false, SupportedFeatures, &encoders, nil) accKeeper, keeper := keepers.AccountKeeper, keepers.WasmKeeper - topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000)) - deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000)) - walletA, privKeyA := CreateFakeFundedAccount(ctx, accKeeper, keeper.bankKeeper, deposit.Add(deposit...)) - walletB, privKeyB := CreateFakeFundedAccount(ctx, accKeeper, keeper.bankKeeper, topUp) + walletA, privKeyA := CreateFakeFundedAccount(ctx, accKeeper, keeper.bankKeeper, sdk.NewCoins(sdk.NewInt64Coin("denom", 200000), sdk.NewInt64Coin("assaf", 200000))) + walletB, privKeyB := CreateFakeFundedAccount(ctx, accKeeper, keeper.bankKeeper, sdk.NewCoins(sdk.NewInt64Coin("denom", 5000), sdk.NewInt64Coin("assaf", 5000))) wasmCode, err := ioutil.ReadFile(wasmPath) require.NoError(t, err) @@ -401,13 +399,13 @@ func initHelper( codeID uint64, creator sdk.AccAddress, creatorPrivKey crypto.PrivKey, initMsg string, isErrorEncrypted bool, isV1Contract bool, gas uint64, ) (sdk.AccAddress, []ContractEvent, cosmwasm.StdError) { - return initHelperImpl(t, keeper, ctx, codeID, creator, creatorPrivKey, initMsg, isErrorEncrypted, isV1Contract, gas, -1, 0) + return initHelperImpl(t, keeper, ctx, codeID, creator, creatorPrivKey, initMsg, isErrorEncrypted, isV1Contract, gas, -1, sdk.NewCoins()) } func initHelperImpl( t *testing.T, keeper Keeper, ctx sdk.Context, codeID uint64, creator sdk.AccAddress, creatorPrivKey crypto.PrivKey, initMsg string, - isErrorEncrypted bool, isV1Contract bool, gas uint64, wasmCallCount int64, coin int64, + isErrorEncrypted bool, isV1Contract bool, gas uint64, wasmCallCount int64, coins sdk.Coins, ) (sdk.AccAddress, []ContractEvent, cosmwasm.StdError) { hashStr := hex.EncodeToString(keeper.GetCodeInfo(ctx, codeID).CodeHash) @@ -431,9 +429,9 @@ func initHelperImpl( log.NewNopLogger(), ).WithGasMeter(gasMeter) - ctx = PrepareInitSignedTx(t, keeper, ctx, creator, creatorPrivKey, initMsgBz, codeID, sdk.NewCoins(sdk.NewInt64Coin("denom", coin))) + ctx = PrepareInitSignedTx(t, keeper, ctx, creator, creatorPrivKey, initMsgBz, codeID, coins) // make the label a random base64 string, because why not? - contractAddress, _, err := keeper.Instantiate(ctx, codeID, creator /* nil,*/, initMsgBz, base64.RawURLEncoding.EncodeToString(nonce), sdk.NewCoins(sdk.NewInt64Coin("denom", coin)), nil) + contractAddress, _, err := keeper.Instantiate(ctx, codeID, creator /* nil,*/, initMsgBz, base64.RawURLEncoding.EncodeToString(nonce), coins, nil) if wasmCallCount < 0 { // default, just check that at least 1 call happened @@ -2025,7 +2023,7 @@ func TestGasIsChargedForInitCallbackToInit(t *testing.T) { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) - _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"callback_to_init":{"code_id":%d,"code_hash":"%s"}}`, codeID, codeHash), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"callback_to_init":{"code_id":%d,"code_hash":"%s"}}`, codeID, codeHash), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.Empty(t, err) }) } @@ -2039,7 +2037,7 @@ func TestGasIsChargedForInitCallbackToExec(t *testing.T) { addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) - _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"callback":{"contract_addr":"%s","code_hash":"%s"}}`, addr, codeHash), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"callback":{"contract_addr":"%s","code_hash":"%s"}}`, addr, codeHash), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.Empty(t, err) }) } @@ -2101,7 +2099,7 @@ func TestGasIsChargedForInitExternalQuery(t *testing.T) { addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) - _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"send_external_query_depth_counter":{"to":"%s","depth":2,"code_hash":"%s"}}`, addr.String(), codeHash), true, testContract.IsCosmWasmV1, defaultGasForTests, 3, 0) + _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"send_external_query_depth_counter":{"to":"%s","depth":2,"code_hash":"%s"}}`, addr.String(), codeHash), true, testContract.IsCosmWasmV1, defaultGasForTests, 3, sdk.NewCoins()) require.Empty(t, err) }) } @@ -2271,7 +2269,7 @@ func TestCodeHashInitCallInit(t *testing.T) { ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) t.Run("GoodCodeHash", func(t *testing.T) { - addr, events, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"%s","msg":"%s","label":"1"}}`, codeID, codeHash, `{\"nop\":{}}`), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + addr, events, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"%s","msg":"%s","label":"1"}}`, codeID, codeHash, `{\"nop\":{}}`), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.Empty(t, err) require.Equal(t, @@ -2289,7 +2287,7 @@ func TestCodeHashInitCallInit(t *testing.T) { ) }) t.Run("EmptyCodeHash", func(t *testing.T) { - _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"","msg":"%s","label":"2"}}`, codeID, `{\"nop\":{}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"","msg":"%s","label":"2"}}`, codeID, `{\"nop\":{}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.NotEmpty(t, err) require.Contains(t, @@ -2298,7 +2296,7 @@ func TestCodeHashInitCallInit(t *testing.T) { ) }) t.Run("TooBigCodeHash", func(t *testing.T) { - _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"%sa","msg":"%s","label":"3"}}`, codeID, codeHash, `{\"nop\":{}}`), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"%sa","msg":"%s","label":"3"}}`, codeID, codeHash, `{\"nop\":{}}`), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.NotEmpty(t, err) require.Contains(t, @@ -2307,7 +2305,7 @@ func TestCodeHashInitCallInit(t *testing.T) { ) }) t.Run("TooSmallCodeHash", func(t *testing.T) { - _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"%s","msg":"%s","label":"4"}}`, codeID, codeHash[0:63], `{\"nop\":{}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"%s","msg":"%s","label":"4"}}`, codeID, codeHash[0:63], `{\"nop\":{}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.NotEmpty(t, err) require.Contains(t, @@ -2316,7 +2314,7 @@ func TestCodeHashInitCallInit(t *testing.T) { ) }) t.Run("IncorrectCodeHash", func(t *testing.T) { - _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","msg":"%s","label":"5"}}`, codeID, `{\"nop\":{}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","msg":"%s","label":"5"}}`, codeID, `{\"nop\":{}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.NotEmpty(t, err) require.Contains(t, @@ -2333,11 +2331,11 @@ func TestCodeHashInitCallExec(t *testing.T) { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) - addr, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests, 1, 0) + addr, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests, 1, sdk.NewCoins()) require.Empty(t, err) t.Run("GoodCodeHash", func(t *testing.T) { - addr2, events, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_exec":{"addr":"%s","code_hash":"%s","msg":"%s"}}`, addr.String(), codeHash, `{\"c\":{\"x\":1,\"y\":1}}`), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + addr2, events, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_exec":{"addr":"%s","code_hash":"%s","msg":"%s"}}`, addr.String(), codeHash, `{\"c\":{\"x\":1,\"y\":1}}`), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.Empty(t, err) require.Equal(t, @@ -2355,7 +2353,7 @@ func TestCodeHashInitCallExec(t *testing.T) { ) }) t.Run("EmptyCodeHash", func(t *testing.T) { - _, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_exec":{"addr":"%s","code_hash":"","msg":"%s"}}`, addr.String(), `{\"c\":{\"x\":1,\"y\":1}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + _, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_exec":{"addr":"%s","code_hash":"","msg":"%s"}}`, addr.String(), `{\"c\":{\"x\":1,\"y\":1}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.NotEmpty(t, err) require.Contains(t, @@ -2364,7 +2362,7 @@ func TestCodeHashInitCallExec(t *testing.T) { ) }) t.Run("TooBigCodeHash", func(t *testing.T) { - _, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_exec":{"addr":"%s","code_hash":"%sa","msg":"%s"}}`, addr.String(), codeHash, `{\"c\":{\"x\":1,\"y\":1}}`), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + _, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_exec":{"addr":"%s","code_hash":"%sa","msg":"%s"}}`, addr.String(), codeHash, `{\"c\":{\"x\":1,\"y\":1}}`), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.NotEmpty(t, err) require.Contains(t, @@ -2373,7 +2371,7 @@ func TestCodeHashInitCallExec(t *testing.T) { ) }) t.Run("TooSmallCodeHash", func(t *testing.T) { - _, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_exec":{"addr":"%s","code_hash":"%s","msg":"%s"}}`, addr.String(), codeHash[0:63], `{\"c\":{\"x\":1,\"y\":1}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + _, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_exec":{"addr":"%s","code_hash":"%s","msg":"%s"}}`, addr.String(), codeHash[0:63], `{\"c\":{\"x\":1,\"y\":1}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.NotEmpty(t, err) require.Contains(t, @@ -2382,7 +2380,7 @@ func TestCodeHashInitCallExec(t *testing.T) { ) }) t.Run("IncorrectCodeHash", func(t *testing.T) { - _, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_exec":{"addr":"%s","code_hash":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","msg":"%s"}}`, addr.String(), `{\"c\":{\"x\":1,\"y\":1}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, 0) + _, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_exec":{"addr":"%s","code_hash":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","msg":"%s"}}`, addr.String(), `{\"c\":{\"x\":1,\"y\":1}}`), false, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.NotEmpty(t, err) require.Contains(t, @@ -3404,3 +3402,102 @@ func TestV1ReplyLoop(t *testing.T) { require.Empty(t, err) require.Equal(t, uint32(20), binary.BigEndian.Uint32(data)) } + +func TestBankMsgSend(t *testing.T) { + for _, contract := range testContracts { + t.Run(contract.CosmWasmVersion, func(t *testing.T) { + + for _, callType := range []string{"init", "exec"} { + t.Run(callType, func(t *testing.T) { + + for _, test := range []struct { + description string + input string + isSuccuss bool + errorMsg string + balancesBefore string + balancesAfter string + }{ + { + description: "regular", + input: `[{"amount":"2","denom":"denom"}]`, + isSuccuss: true, + balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "199998assaf,199998denom 5000assaf,5002denom", + }, + { + description: "multi-coin", + input: `[{"amount":"1","denom":"assaf"},{"amount":"1","denom":"denom"}]`, + isSuccuss: true, + balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "199998assaf,199998denom 5001assaf,5001denom", + }, + { + description: "zero", + input: `[{"amount":"0","denom":"denom"}]`, + isSuccuss: false, + errorMsg: "encrypted: dispatch: submessages: 0denom: invalid coins", + balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "199998assaf,199998denom 5000assaf,5000denom", + }, + { + description: "insufficient funds", + input: `[{"amount":"3","denom":"denom"}]`, + isSuccuss: false, + balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "199998assaf,199998denom 5000assaf,5000denom", + errorMsg: "encrypted: dispatch: submessages: 2denom is smaller than 3denom: insufficient funds", + }, + { + description: "non-existing denom", + input: `[{"amount":"1","denom":"blabla"}]`, + isSuccuss: false, + balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "199998assaf,199998denom 5000assaf,5000denom", + errorMsg: "encrypted: dispatch: submessages: 0blabla is smaller than 1blabla: insufficient funds", + }, + { + description: "none", + input: `[]`, + isSuccuss: true, + balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "199998assaf,199998denom 5000assaf,5000denom", + }, + } { + t.Run(test.description, func(t *testing.T) { + ctx, keeper, codeID, _, walletA, privKeyA, walletB, _ := setupTest(t, contract.WasmFilePath) + + walletACoinsBefore := keeper.bankKeeper.GetAllBalances(ctx, walletA) + walletBCoinsBefore := keeper.bankKeeper.GetAllBalances(ctx, walletB) + + require.Equal(t, test.balancesBefore, walletACoinsBefore.String()+" "+walletBCoinsBefore.String()) + + var err cosmwasm.StdError + var contractAddress sdk.AccAddress + + if callType == "init" { + contractAddress, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"bank_msg":{"to":"%s","amount":%s}}`, walletB.String(), test.input), false, contract.IsCosmWasmV1, defaultGasForTests, -1, sdk.NewCoins(sdk.NewInt64Coin("denom", 2), sdk.NewInt64Coin("assaf", 2))) + } else { + contractAddress, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, false, contract.IsCosmWasmV1, defaultGasForTests, -1, sdk.NewCoins(sdk.NewInt64Coin("denom", 2), sdk.NewInt64Coin("assaf", 2))) + + _, _, _, err = execHelper(t, keeper, ctx, contractAddress, walletA, privKeyA, fmt.Sprintf(`{"bank_msg":{"to":"%s","amount":%s}}`, walletB.String(), test.input), false, contract.IsCosmWasmV1, math.MaxUint64, 0) + } + + if test.isSuccuss { + require.Empty(t, err) + } else { + require.NotEmpty(t, err) + require.Equal(t, err.Error(), test.errorMsg) + } + + walletACoinsAfter := keeper.bankKeeper.GetAllBalances(ctx, walletA) + walletBCoinsAfter := keeper.bankKeeper.GetAllBalances(ctx, walletB) + + require.Equal(t, test.balancesAfter, walletACoinsAfter.String()+" "+walletBCoinsAfter.String()) + }) + } + }) + } + }) + } +} diff --git a/x/compute/internal/keeper/test_common.go b/x/compute/internal/keeper/test_common.go index 9007e7bad..cb9639ac0 100644 --- a/x/compute/internal/keeper/test_common.go +++ b/x/compute/internal/keeper/test_common.go @@ -496,8 +496,7 @@ func PrepareInitSignedTx(t *testing.T, keeper Keeper, ctx sdk.Context, creator s require.NoError(t, err) initMsg := wasmtypes.MsgInstantiateContract{ - Sender: creator, - // Admin: nil, + Sender: creator, CodeID: codeID, Label: "demo contract 1", InitMsg: encMsg, diff --git a/x/compute/internal/keeper/testdata/test-contract/src/contract.rs b/x/compute/internal/keeper/testdata/test-contract/src/contract.rs index a816ecc97..6c25f3019 100644 --- a/x/compute/internal/keeper/testdata/test-contract/src/contract.rs +++ b/x/compute/internal/keeper/testdata/test-contract/src/contract.rs @@ -73,6 +73,10 @@ pub enum InitMsg { InitFromV1 { counter: u64, }, + BankMsg { + amount: Vec, + to: HumanAddr, + }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -164,6 +168,10 @@ pub enum HandleMsg { to: HumanAddr, from: HumanAddr, }, + BankMsg { + amount: Vec, + to: HumanAddr, + }, SendFundsToInitCallback { amount: u32, denom: String, @@ -409,6 +417,14 @@ pub fn init( log: vec![], }) } + InitMsg::BankMsg { to, amount: coins } => Ok(InitResponse { + messages: vec![CosmosMsg::Bank(BankMsg::Send { + from_address: env.contract.address, + to_address: to, + amount: coins, + })], + log: vec![], + }), } } @@ -622,6 +638,15 @@ pub fn handle( log: vec![], data: None, }), + HandleMsg::BankMsg { to, amount } => Ok(HandleResponse { + messages: vec![CosmosMsg::Bank(BankMsg::Send { + from_address: env.contract.address, + to_address: to, + amount, + })], + log: vec![], + data: None, + }), HandleMsg::SendFundsToInitCallback { amount, denom, diff --git a/x/compute/internal/keeper/testdata/v1-sanity-contract/src/contract.rs b/x/compute/internal/keeper/testdata/v1-sanity-contract/src/contract.rs index bc4aef575..8eb1681b9 100644 --- a/x/compute/internal/keeper/testdata/v1-sanity-contract/src/contract.rs +++ b/x/compute/internal/keeper/testdata/v1-sanity-contract/src/contract.rs @@ -144,6 +144,12 @@ pub fn instantiate( Ok(Response::new().add_attribute("c", format!("{}", answer))) } + InstantiateMsg::BankMsg { to, amount } => { + Ok(Response::new().add_message(CosmosMsg::Bank(BankMsg::Send { + to_address: to, + amount, + }))) + } } } @@ -532,6 +538,12 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> S return res; } + ExecuteMsg::BankMsg { to, amount } => { + Ok(Response::new().add_message(CosmosMsg::Bank(BankMsg::Send { + to_address: to, + amount, + }))) + } } } diff --git a/x/compute/internal/keeper/testdata/v1-sanity-contract/src/msg.rs b/x/compute/internal/keeper/testdata/v1-sanity-contract/src/msg.rs index 100cd6414..23320f5c8 100644 --- a/x/compute/internal/keeper/testdata/v1-sanity-contract/src/msg.rs +++ b/x/compute/internal/keeper/testdata/v1-sanity-contract/src/msg.rs @@ -1,8 +1,8 @@ -use cosmwasm_std::Binary; +use cosmwasm_std::{Binary, Coin}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] #[serde(rename_all = "snake_case")] pub enum InstantiateMsg { Counter { @@ -59,6 +59,10 @@ pub enum InstantiateMsg { code_hash: String, msg: String, }, + BankMsg { + amount: Vec, + to: String, + }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] @@ -256,6 +260,10 @@ pub enum ExecuteMsg { privkey: Binary, iterations: u32, }, + BankMsg { + amount: Vec, + to: String, + }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] From bbc6e6c930dd8f817ac8e29b024f2604610ec460 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 12 Jul 2022 16:04:50 +0300 Subject: [PATCH 02/16] Fix some clippy errors --- cosmwasm/enclaves/shared/contract-engine/src/io.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cosmwasm/enclaves/shared/contract-engine/src/io.rs b/cosmwasm/enclaves/shared/contract-engine/src/io.rs index bc4ac974f..c6e302331 100644 --- a/cosmwasm/enclaves/shared/contract-engine/src/io.rs +++ b/cosmwasm/enclaves/shared/contract-engine/src/io.rs @@ -155,7 +155,7 @@ pub fn encrypt_output( nonce: IoNonce, user_public_key: Ed25519PublicKey, contract_addr: &CanonicalAddr, - contract_hash: &String, + contract_hash: &str, reply_params: Option<(Vec, u64)>, sender_addr: &CanonicalAddr, is_query_output: bool, @@ -217,7 +217,7 @@ pub fn encrypt_output( let tmp_secret_msg = SecretMessage { nonce, user_public_key, - msg: reply_as_vec.clone(), + msg: reply_as_vec, }; Some(Binary::from( @@ -391,7 +391,7 @@ pub fn encrypt_output( let tmp_secret_msg = SecretMessage { nonce, user_public_key, - msg: reply_as_vec.clone(), + msg: reply_as_vec, }; Some(Binary::from( @@ -533,7 +533,7 @@ fn encrypt_v1_wasm_msg( nonce: IoNonce, user_public_key: Ed25519PublicKey, contract_addr: &CanonicalAddr, - reply_recipient_contract_hash: &String, + reply_recipient_contract_hash: &str, ) -> Result<(), EnclaveError> { match wasm_msg { enclave_cosmwasm_v1_types::results::WasmMsg::Execute { From 56bd1523b1c706842300ec2acd7de4db947f2b81 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 12 Jul 2022 16:43:52 +0300 Subject: [PATCH 03/16] Refactor setupTest for easier coin creation --- x/compute/internal/keeper/keeper_test.go | 4 +- .../keeper/param_verification_test.go | 34 +-- .../internal/keeper/secret_contracts_test.go | 232 +++++++++--------- 3 files changed, 134 insertions(+), 136 deletions(-) diff --git a/x/compute/internal/keeper/keeper_test.go b/x/compute/internal/keeper/keeper_test.go index 63cfd768e..d87a78a87 100644 --- a/x/compute/internal/keeper/keeper_test.go +++ b/x/compute/internal/keeper/keeper_test.go @@ -423,7 +423,7 @@ func TestInstantiateWithDeposit(t *testing.T) { } for msg, spec := range specs { t.Run(msg, func(t *testing.T) { - ctx, keeper, codeID, _, _, _, _, _ := setupTest(t, "./testdata/contract.wasm") + ctx, keeper, codeID, _, _, _, _, _ := setupTest(t, "./testdata/contract.wasm", sdk.NewCoins()) deposit := 100 var funds int64 = 0 @@ -721,7 +721,7 @@ func TestExecuteWithDeposit(t *testing.T) { } for msg, spec := range specs { t.Run(msg, func(t *testing.T) { - ctx, keeper, codeID, _, _, _, _, _ := setupTest(t, "./testdata/contract.wasm") + ctx, keeper, codeID, _, _, _, _, _ := setupTest(t, "./testdata/contract.wasm", sdk.NewCoins()) deposit := int64(100) var funds int64 = 0 diff --git a/x/compute/internal/keeper/param_verification_test.go b/x/compute/internal/keeper/param_verification_test.go index 146b9f3d3..8a3f60988 100644 --- a/x/compute/internal/keeper/param_verification_test.go +++ b/x/compute/internal/keeper/param_verification_test.go @@ -206,7 +206,7 @@ func prepareInitSignedTxMultipleMsgs( func TestMultipleSigners(t *testing.T) { // t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, codeHash, walletA, privKeyA, walletB, privKeyB := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, walletA, privKeyA, walletB, privKeyB := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) initMsg := `{"nop":{}}` @@ -284,7 +284,7 @@ func TestMultipleSigners(t *testing.T) { func TestWrongSigner(t *testing.T) { t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, _, walletA, _, walletB, privKeyB := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, _, walletA, _, walletB, privKeyB := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) initMsg := `{"nop":{}}` @@ -312,7 +312,7 @@ func TestWrongSigner(t *testing.T) { func TestMultiSig(t *testing.T) { t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, codeHash, _, _, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, _, _, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) initMsg := `{"nop":{}}` msg := types.NewSecretMsg([]byte(codeHash), []byte(initMsg)) @@ -353,14 +353,14 @@ func TestMultiSig(t *testing.T) { ) // Reset wasm events - ctx, keeper, codeID, codeHash, _, _, _, _ = setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, _, _, _, _ = setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) } } } func TestMultiSigThreshold(t *testing.T) { t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, codeHash, _, _, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, _, _, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) initMsg := `{"nop":{}}` @@ -405,14 +405,14 @@ func TestMultiSigThreshold(t *testing.T) { ) // Reset wasm events - ctx, keeper, codeID, _, _, _, _, _ = setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, _, _, _, _, _ = setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) } } } func TestMultiSigThresholdNotMet(t *testing.T) { t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, codeHash, _, _, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, _, _, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) initMsg := `{"nop":{}}` @@ -444,7 +444,7 @@ func TestMultiSigThresholdNotMet(t *testing.T) { func TestMultiSigExecute(t *testing.T) { t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, codeHash, _, _, walletB, privKeyB := setupTest(t, "./testdata/erc20.wasm") + ctx, keeper, codeID, codeHash, _, _, walletB, privKeyB := setupTest(t, "./testdata/erc20.wasm", sdk.NewCoins()) accounts, multisigAccount := generateMultisigAccount(ctx, keeper, 5, 4) @@ -501,7 +501,7 @@ func TestMultiSigExecute(t *testing.T) { func TestMultiSigCallbacks(t *testing.T) { t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) // init contractAddress, initEvents, error := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, false, defaultGasForTests) @@ -567,7 +567,7 @@ func TestMultiSigCallbacks(t *testing.T) { func TestMultiSigInMultiSig(t *testing.T) { t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, codeHash, _, privKeyA, _, privKeyB := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, _, privKeyA, _, privKeyB := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) accounts, multisigAccount := generateMultisigAccount(ctx, keeper, 5, 3) multiSigPubKeys := []crypto.PubKey{multisigAccount.public, privKeyA.PubKey(), privKeyB.PubKey()} @@ -672,7 +672,7 @@ func TestMultiSigInMultiSig(t *testing.T) { func TestMultiSigInMultiSigDifferentOrder(t *testing.T) { t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, codeHash, _, privKeyA, _, privKeyB := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, _, privKeyA, _, privKeyB := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) accounts, multisigAccount := generateMultisigAccount(ctx, keeper, 5, 3) multiSigPubKeys := []crypto.PubKey{multisigAccount.public, privKeyA.PubKey(), privKeyB.PubKey()} @@ -777,7 +777,7 @@ func TestMultiSigInMultiSigDifferentOrder(t *testing.T) { func TestInvalidKeyType(t *testing.T) { t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, codeHash, _, _, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, _, _, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) edKey := ed25519.GenPrivKey() edPub := edKey.PubKey() @@ -822,7 +822,7 @@ func TestInvalidKeyType(t *testing.T) { func TestInvalidKeyTypeInMultisig(t *testing.T) { t.SkipNow() // skipping till multisig is fixed - ctx, keeper, codeID, codeHash, _, privKeyA, _, privKeyB := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, _, privKeyA, _, privKeyB := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) edKey := ed25519.GenPrivKey() edPub := edKey.PubKey() @@ -912,7 +912,7 @@ func TestInvalidKeyTypeInMultisig(t *testing.T) { func TestWrongFundsNoFunds(t *testing.T) { t.SkipNow() - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) initMsg := `{"nop":{}}` @@ -937,7 +937,7 @@ func TestWrongFundsNoFunds(t *testing.T) { func TestWrongFundsSomeFunds(t *testing.T) { t.SkipNow() - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) initMsg := `{"nop":{}}` @@ -962,7 +962,7 @@ func TestWrongFundsSomeFunds(t *testing.T) { func TestWrongMessage(t *testing.T) { t.SkipNow() - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) initMsg := `{"nop":{}}` @@ -997,7 +997,7 @@ func TestWrongMessage(t *testing.T) { func TestWrongContractAddress(t *testing.T) { t.SkipNow() - ctx, keeper, codeID, codeHash, walletA, privKeyA, walletB, privKeyB := setupTest(t, "./testdata/erc20.wasm") + ctx, keeper, codeID, codeHash, walletA, privKeyA, walletB, privKeyB := setupTest(t, "./testdata/erc20.wasm", sdk.NewCoins()) initMsg := fmt.Sprintf(`{"decimals":10,"initial_balances":[{"address":"%s","amount":"108"},{"address":"%s","amount":"53"}],"name":"ReuvenPersonalRustCoin","symbol":"RPRC"}`, walletA.String(), walletB.String()) diff --git a/x/compute/internal/keeper/secret_contracts_test.go b/x/compute/internal/keeper/secret_contracts_test.go index b97ec9f7b..a36aa24b2 100644 --- a/x/compute/internal/keeper/secret_contracts_test.go +++ b/x/compute/internal/keeper/secret_contracts_test.go @@ -70,7 +70,7 @@ func testEncrypt(t *testing.T, keeper Keeper, ctx sdk.Context, contractAddress s return queryBz, nil } -func setupTest(t *testing.T, wasmPath string) (sdk.Context, Keeper, uint64, string, sdk.AccAddress, crypto.PrivKey, sdk.AccAddress, crypto.PrivKey) { +func setupTest(t *testing.T, wasmPath string, additionalCoinsInWallets sdk.Coins) (sdk.Context, Keeper, uint64, string, sdk.AccAddress, crypto.PrivKey, sdk.AccAddress, crypto.PrivKey) { encodingConfig := MakeEncodingConfig() var transferPortSource types.ICS20TransferPortSource transferPortSource = MockIBCTransferKeeper{GetPortFn: func(ctx sdk.Context) string { @@ -80,8 +80,8 @@ func setupTest(t *testing.T, wasmPath string) (sdk.Context, Keeper, uint64, stri ctx, keepers := CreateTestInput(t, false, SupportedFeatures, &encoders, nil) accKeeper, keeper := keepers.AccountKeeper, keepers.WasmKeeper - walletA, privKeyA := CreateFakeFundedAccount(ctx, accKeeper, keeper.bankKeeper, sdk.NewCoins(sdk.NewInt64Coin("denom", 200000), sdk.NewInt64Coin("assaf", 200000))) - walletB, privKeyB := CreateFakeFundedAccount(ctx, accKeeper, keeper.bankKeeper, sdk.NewCoins(sdk.NewInt64Coin("denom", 5000), sdk.NewInt64Coin("assaf", 5000))) + walletA, privKeyA := CreateFakeFundedAccount(ctx, accKeeper, keeper.bankKeeper, sdk.NewCoins(sdk.NewInt64Coin("denom", 200000)).Add(additionalCoinsInWallets...)) + walletB, privKeyB := CreateFakeFundedAccount(ctx, accKeeper, keeper.bankKeeper, sdk.NewCoins(sdk.NewInt64Coin("denom", 5000)).Add(additionalCoinsInWallets...)) wasmCode, err := ioutil.ReadFile(wasmPath) require.NoError(t, err) @@ -405,7 +405,7 @@ func initHelper( func initHelperImpl( t *testing.T, keeper Keeper, ctx sdk.Context, codeID uint64, creator sdk.AccAddress, creatorPrivKey crypto.PrivKey, initMsg string, - isErrorEncrypted bool, isV1Contract bool, gas uint64, wasmCallCount int64, coins sdk.Coins, + isErrorEncrypted bool, isV1Contract bool, gas uint64, wasmCallCount int64, sentFunds sdk.Coins, ) (sdk.AccAddress, []ContractEvent, cosmwasm.StdError) { hashStr := hex.EncodeToString(keeper.GetCodeInfo(ctx, codeID).CodeHash) @@ -429,9 +429,9 @@ func initHelperImpl( log.NewNopLogger(), ).WithGasMeter(gasMeter) - ctx = PrepareInitSignedTx(t, keeper, ctx, creator, creatorPrivKey, initMsgBz, codeID, coins) + ctx = PrepareInitSignedTx(t, keeper, ctx, creator, creatorPrivKey, initMsgBz, codeID, sentFunds) // make the label a random base64 string, because why not? - contractAddress, _, err := keeper.Instantiate(ctx, codeID, creator /* nil,*/, initMsgBz, base64.RawURLEncoding.EncodeToString(nonce), coins, nil) + contractAddress, _, err := keeper.Instantiate(ctx, codeID, creator /* nil,*/, initMsgBz, base64.RawURLEncoding.EncodeToString(nonce), sentFunds, nil) if wasmCallCount < 0 { // default, just check that at least 1 call happened @@ -455,7 +455,7 @@ func initHelperImpl( func TestCallbackSanity(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) // init contractAddress, initEvents, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -496,7 +496,7 @@ func TestCallbackSanity(t *testing.T) { } func TestSanity(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, walletB, _ := setupTest(t, "./testdata/erc20.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, walletB, _ := setupTest(t, "./testdata/erc20.wasm", sdk.NewCoins()) // init initMsg := fmt.Sprintf(`{"decimals":10,"initial_balances":[{"address":"%s","amount":"108"},{"address":"%s","amount":"53"}],"name":"ReuvenPersonalRustCoin","symbol":"RPRC"}`, walletA.String(), walletB.String()) @@ -545,7 +545,7 @@ func TestSanity(t *testing.T) { func TestInitLogs(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, initEvents, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -566,7 +566,7 @@ func TestInitLogs(t *testing.T) { func TestEmptyLogKeyValue(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -591,7 +591,7 @@ func TestEmptyLogKeyValue(t *testing.T) { func TestEmptyData(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -607,7 +607,7 @@ func TestEmptyData(t *testing.T) { func TestNoData(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -623,7 +623,7 @@ func TestNoData(t *testing.T) { func TestExecuteIllegalInputError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -643,7 +643,7 @@ func TestExecuteIllegalInputError(t *testing.T) { func TestInitIllegalInputError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) _, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `bad input`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -660,7 +660,7 @@ func TestInitIllegalInputError(t *testing.T) { func TestCallbackFromInitAndCallbackEvents(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) // init first contract so we'd have someone to callback firstContractAddress, initEvents, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -698,7 +698,7 @@ func TestCallbackFromInitAndCallbackEvents(t *testing.T) { } func TestQueryInputParamError(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, walletB, _ := setupTest(t, "./testdata/erc20.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, walletB, _ := setupTest(t, "./testdata/erc20.wasm", sdk.NewCoins()) // init initMsg := fmt.Sprintf(`{"decimals":10,"initial_balances":[{"address":"%s","amount":"108"},{"address":"%s","amount":"53"}],"name":"ReuvenPersonalRustCoin","symbol":"RPRC"}`, walletA.String(), walletB.String()) @@ -716,7 +716,7 @@ func TestQueryInputParamError(t *testing.T) { func TestUnicodeData(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -732,7 +732,7 @@ func TestUnicodeData(t *testing.T) { func TestInitContractError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) t.Run("generic_err", func(t *testing.T) { _, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"contract_error":{"error_type":"generic_err"}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -830,7 +830,7 @@ func TestInitContractError(t *testing.T) { func TestExecContractError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -931,7 +931,7 @@ func TestExecContractError(t *testing.T) { func TestQueryContractError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1032,7 +1032,7 @@ func TestQueryContractError(t *testing.T) { func TestInitParamError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) codeHash := "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" msg := fmt.Sprintf(`{"callback":{"contract_addr":"notanaddress", "code_hash":"%s"}}`, codeHash) @@ -1047,7 +1047,7 @@ func TestInitParamError(t *testing.T) { func TestCallbackExecuteParamError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1062,7 +1062,7 @@ func TestCallbackExecuteParamError(t *testing.T) { } func TestQueryInputStructureError(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, walletB, _ := setupTest(t, "./testdata/erc20.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, walletB, _ := setupTest(t, "./testdata/erc20.wasm", sdk.NewCoins()) // init initMsg := fmt.Sprintf(`{"decimals":10,"initial_balances":[{"address":"%s","amount":"108"},{"address":"%s","amount":"53"}],"name":"ReuvenPersonalRustCoin","symbol":"RPRC"}`, walletA.String(), walletB.String()) @@ -1080,7 +1080,7 @@ func TestQueryInputStructureError(t *testing.T) { func TestInitNotEncryptedInputError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKey, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKey, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) //ctx = sdk.NewContext( // ctx.MultiStore(), @@ -1105,7 +1105,7 @@ func TestInitNotEncryptedInputError(t *testing.T) { func TestExecuteNotEncryptedInputError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1132,7 +1132,7 @@ func TestExecuteNotEncryptedInputError(t *testing.T) { func TestQueryNotEncryptedInputError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1148,7 +1148,7 @@ func TestQueryNotEncryptedInputError(t *testing.T) { func TestInitNoLogs(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) // init _, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"no_logs":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -1162,7 +1162,7 @@ func TestInitNoLogs(t *testing.T) { func TestExecNoLogs(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) // init contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -1179,7 +1179,7 @@ func TestExecNoLogs(t *testing.T) { func TestExecCallbackToInit(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) // init first contract contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -1220,7 +1220,7 @@ func TestExecCallbackToInit(t *testing.T) { func TestInitCallbackToInit(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, initEvents, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"callback_to_init":{"code_id":%d, "code_hash":"%s"}}`, codeID, codeHash), true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1255,7 +1255,7 @@ func TestInitCallbackToInit(t *testing.T) { func TestInitCallbackContractError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, initEvents, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1274,7 +1274,7 @@ func TestInitCallbackContractError(t *testing.T) { func TestExecCallbackContractError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) // init contractAddress, initEvents, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -1294,7 +1294,7 @@ func TestExecCallbackContractError(t *testing.T) { func TestExecCallbackBadParam(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) // init contractAddress, initEvents, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -1321,7 +1321,7 @@ func TestExecCallbackBadParam(t *testing.T) { func TestInitCallbackBadParam(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) // init first contractAddress, initEvents, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -1348,7 +1348,7 @@ func TestInitCallbackBadParam(t *testing.T) { func TestState(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) // init contractAddress, initEvents, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -1379,7 +1379,7 @@ func TestState(t *testing.T) { func TestCanonicalizeAddressErrors(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, initEvents, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1396,7 +1396,7 @@ func TestCanonicalizeAddressErrors(t *testing.T) { func TestInitPanic(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) _, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"panic":{}}`, false, testContract.IsCosmWasmV1, defaultGasForTests) @@ -1409,7 +1409,7 @@ func TestInitPanic(t *testing.T) { func TestExecPanic(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1425,7 +1425,7 @@ func TestExecPanic(t *testing.T) { func TestQueryPanic(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1440,7 +1440,7 @@ func TestQueryPanic(t *testing.T) { func TestAllocateOnHeapFailBecauseMemoryLimit(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1460,7 +1460,7 @@ func TestAllocateOnHeapFailBecauseMemoryLimit(t *testing.T) { func TestAllocateOnHeapFailBecauseGasLimit(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1490,7 +1490,7 @@ func TestAllocateOnHeapFailBecauseGasLimit(t *testing.T) { func TestAllocateOnHeapMoreThanSGXHasFailBecauseMemoryLimit(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1512,7 +1512,7 @@ func TestAllocateOnHeapMoreThanSGXHasFailBecauseMemoryLimit(t *testing.T) { func TestPassNullPointerToImports(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1545,7 +1545,7 @@ func TestPassNullPointerToImports(t *testing.T) { func TestExternalQueryWorks(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1561,7 +1561,7 @@ func TestExternalQueryWorks(t *testing.T) { func TestExternalQueryCalleePanic(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -1576,7 +1576,7 @@ func TestExternalQueryCalleePanic(t *testing.T) { func TestExternalQueryCalleeStdError(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -1592,7 +1592,7 @@ func TestExternalQueryCalleeStdError(t *testing.T) { func TestExternalQueryCalleeDoesntExist(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -1608,7 +1608,7 @@ func TestExternalQueryCalleeDoesntExist(t *testing.T) { func TestExternalQueryBadSenderABI(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -1632,7 +1632,7 @@ func TestExternalQueryBadSenderABI(t *testing.T) { func TestExternalQueryBadReceiverABI(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -1655,7 +1655,7 @@ func TestExternalQueryBadReceiverABI(t *testing.T) { func TestMsgSenderInCallback(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -1681,7 +1681,7 @@ func TestInfiniteQueryLoopKilledGracefullyByOOM(t *testing.T) { t.SkipNow() // We no longer expect to hit OOM trivially for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -1698,7 +1698,7 @@ func TestInfiniteQueryLoopKilledGracefullyByOOM(t *testing.T) { func TestQueryRecursionLimitEnforcedInQueries(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -1716,7 +1716,7 @@ func TestQueryRecursionLimitEnforcedInQueries(t *testing.T) { func TestQueryRecursionLimitEnforcedInHandles(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -1734,7 +1734,7 @@ func TestQueryRecursionLimitEnforcedInHandles(t *testing.T) { func TestQueryRecursionLimitEnforcedInInits(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) // Initialize a contract that we will be querying addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -1759,7 +1759,7 @@ func TestQueryRecursionLimitEnforcedInInits(t *testing.T) { func TestWriteToStorageDuringQuery(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1774,7 +1774,7 @@ func TestWriteToStorageDuringQuery(t *testing.T) { func TestRemoveFromStorageDuringQuery(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1789,7 +1789,7 @@ func TestRemoveFromStorageDuringQuery(t *testing.T) { func TestDepositToContract(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1818,7 +1818,7 @@ func TestDepositToContract(t *testing.T) { func TestContractSendFunds(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1848,7 +1848,7 @@ func TestContractSendFunds(t *testing.T) { // In V1 there is no "from" field in Bank message functionality which means it shouldn't be tested func TestContractTryToSendFundsFromSomeoneElse(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, false, defaultGasForTests) require.Empty(t, initErr) @@ -1872,7 +1872,7 @@ func TestContractTryToSendFundsFromSomeoneElse(t *testing.T) { func TestContractSendFundsToInitCallback(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1905,7 +1905,7 @@ func TestContractSendFundsToInitCallback(t *testing.T) { func TestContractSendFundsToInitCallbackNotEnough(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1935,7 +1935,7 @@ func TestContractSendFundsToInitCallbackNotEnough(t *testing.T) { func TestContractSendFundsToExecCallback(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -1969,7 +1969,7 @@ func TestContractSendFundsToExecCallback(t *testing.T) { func TestContractSendFundsToExecCallbackNotEnough(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -2004,7 +2004,7 @@ func TestContractSendFundsToExecCallbackNotEnough(t *testing.T) { func TestSleep(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -2021,7 +2021,7 @@ func TestSleep(t *testing.T) { func TestGasIsChargedForInitCallbackToInit(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) _, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"callback_to_init":{"code_id":%d,"code_hash":"%s"}}`, codeID, codeHash), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) require.Empty(t, err) @@ -2032,7 +2032,7 @@ func TestGasIsChargedForInitCallbackToInit(t *testing.T) { func TestGasIsChargedForInitCallbackToExec(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -2046,7 +2046,7 @@ func TestGasIsChargedForInitCallbackToExec(t *testing.T) { func TestGasIsChargedForExecCallbackToInit(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -2061,7 +2061,7 @@ func TestGasIsChargedForExecCallbackToInit(t *testing.T) { func TestGasIsChargedForExecCallbackToExec(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -2078,7 +2078,7 @@ func TestGasIsChargedForExecExternalQuery(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -2094,7 +2094,7 @@ func TestGasIsChargedForInitExternalQuery(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -2110,7 +2110,7 @@ func TestGasIsChargedForQueryExternalQuery(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -2122,7 +2122,7 @@ func TestGasIsChargedForQueryExternalQuery(t *testing.T) { } func TestWasmTooHighInitialMemoryRuntimeFail(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/too-high-initial-memory.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/too-high-initial-memory.wasm", sdk.NewCoins()) _, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, false, false, defaultGasForTests) require.NotNil(t, err.GenericErr) @@ -2152,7 +2152,7 @@ func TestWasmTooHighInitialMemoryStaticFail(t *testing.T) { func TestWasmWithFloatingPoints(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract_with_floats.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/test-contract/contract_with_floats.wasm", sdk.NewCoins()) _, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, false, testContract.IsCosmWasmV1, defaultGasForTests) require.NotNil(t, err.GenericErr) @@ -2164,7 +2164,7 @@ func TestWasmWithFloatingPoints(t *testing.T) { func TestCodeHashInvalid(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) initMsg := []byte(`AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA{"nop":{}`) enc, _ := wasmCtx.Encrypt(initMsg) @@ -2180,7 +2180,7 @@ func TestCodeHashInvalid(t *testing.T) { func TestCodeHashEmpty(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) initMsg := []byte(`{"nop":{}`) enc, _ := wasmCtx.Encrypt(initMsg) @@ -2196,7 +2196,7 @@ func TestCodeHashEmpty(t *testing.T) { func TestCodeHashNotHex(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) initMsg := []byte(`🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉{"nop":{}}`) enc, _ := wasmCtx.Encrypt(initMsg) @@ -2212,7 +2212,7 @@ func TestCodeHashNotHex(t *testing.T) { func TestCodeHashTooSmall(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) initMsg := []byte(codeHash[0:63] + `{"nop":{}`) @@ -2229,7 +2229,7 @@ func TestCodeHashTooSmall(t *testing.T) { func TestCodeHashTooBig(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) initMsg := []byte(codeHash + "a" + `{"nop":{}`) @@ -2249,7 +2249,7 @@ func TestCodeHashTooBig(t *testing.T) { func TestCodeHashWrong(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privWalletA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) initMsg := []byte(`e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855{"nop":{}`) @@ -2266,7 +2266,7 @@ func TestCodeHashWrong(t *testing.T) { func TestCodeHashInitCallInit(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) t.Run("GoodCodeHash", func(t *testing.T) { addr, events, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"call_to_init":{"code_id":%d,"code_hash":"%s","msg":"%s","label":"1"}}`, codeID, codeHash, `{\"nop\":{}}`), true, testContract.IsCosmWasmV1, defaultGasForTests, 2, sdk.NewCoins()) @@ -2329,7 +2329,7 @@ func TestCodeHashInitCallInit(t *testing.T) { func TestCodeHashInitCallExec(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests, 1, sdk.NewCoins()) require.Empty(t, err) @@ -2395,7 +2395,7 @@ func TestCodeHashInitCallExec(t *testing.T) { func TestCodeHashInitCallQuery(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -2457,7 +2457,7 @@ func TestCodeHashInitCallQuery(t *testing.T) { func TestCodeHashExecCallInit(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -2530,7 +2530,7 @@ func TestCodeHashExecCallInit(t *testing.T) { func TestLabelCollisionWhenMultipleCallbacksToInitFromSameContract(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -2549,7 +2549,7 @@ func TestLabelCollisionWhenMultipleCallbacksToInitFromSameContract(t *testing.T) func TestCodeHashExecCallExec(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -2622,7 +2622,7 @@ func TestCodeHashExecCallExec(t *testing.T) { func TestQueryGasPrice(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -2640,7 +2640,7 @@ func TestQueryGasPrice(t *testing.T) { func TestCodeHashExecCallQuery(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -2709,7 +2709,7 @@ func TestCodeHashExecCallQuery(t *testing.T) { func TestCodeHashQueryCallQuery(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, codeHash, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, err) @@ -2768,7 +2768,7 @@ func TestCodeHashQueryCallQuery(t *testing.T) { } func TestEncryptedAndPlaintextLogs(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/plaintext_logs.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/plaintext_logs.wasm", sdk.NewCoins()) addr, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{}`, true, false, defaultGasForTests) require.Empty(t, err) @@ -2792,7 +2792,7 @@ func TestEncryptedAndPlaintextLogs(t *testing.T) { func TestSecp256k1Verify(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -2921,7 +2921,7 @@ func TestBenchmarkSecp256k1VerifyAPI(t *testing.T) { // and not testing.B and I just wanted to quickly get a feel for the perf improvements for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, _ := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -2940,7 +2940,7 @@ func TestBenchmarkSecp256k1VerifyCrate(t *testing.T) { // and not testing.B and I just wanted to quickly get a feel for the perf improvements for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, _ := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -2956,7 +2956,7 @@ func TestBenchmarkSecp256k1VerifyCrate(t *testing.T) { func TestEd25519Verify(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -3025,7 +3025,7 @@ func TestEd25519Verify(t *testing.T) { func TestEd25519BatchVerify(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -3178,7 +3178,7 @@ func TestEd25519BatchVerify(t *testing.T) { func TestSecp256k1RecoverPubkey(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -3216,7 +3216,7 @@ func TestSecp256k1RecoverPubkey(t *testing.T) { func TestSecp256k1Sign(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -3251,7 +3251,7 @@ func TestSecp256k1Sign(t *testing.T) { func TestEd25519Sign(t *testing.T) { for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, initErr := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) require.Empty(t, initErr) @@ -3289,7 +3289,7 @@ func TestBenchmarkEd25519BatchVerifyAPI(t *testing.T) { // and not testing.B and I just wanted to quickly get a feel for the performance improvements for _, testContract := range testContracts { t.Run(testContract.CosmWasmVersion, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, testContract.WasmFilePath, sdk.NewCoins()) contractAddress, _, _ := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, true, testContract.IsCosmWasmV1, defaultGasForTests) @@ -3312,7 +3312,7 @@ type v1QueryResponse struct { } func TestV1EndpointsSanity(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/v1-sanity-contract/contract.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/v1-sanity-contract/contract.wasm", sdk.NewCoins()) contractAddress, _, _ := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"counter":{"counter":10, "expires":100}}`, true, true, defaultGasForTests) @@ -3332,7 +3332,7 @@ func TestV1EndpointsSanity(t *testing.T) { } func TestV1QueryWorksWithEnv(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/v1-sanity-contract/contract.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/v1-sanity-contract/contract.wasm", sdk.NewCoins()) contractAddress, _, _ := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"counter":{"counter":10, "expires":0}}`, true, true, defaultGasForTests) ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 10) @@ -3348,7 +3348,7 @@ func TestV1QueryWorksWithEnv(t *testing.T) { } func TestV1ReplySanity(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/v1-sanity-contract/contract.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/v1-sanity-contract/contract.wasm", sdk.NewCoins()) contractAddress, _, _ := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"counter":{"counter":10, "expires":100}}`, true, true, defaultGasForTests) @@ -3393,7 +3393,7 @@ func TestV1ReplySanity(t *testing.T) { } func TestV1ReplyLoop(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/v1-sanity-contract/contract.wasm") + ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/v1-sanity-contract/contract.wasm", sdk.NewCoins()) contractAddress, _, _ := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"counter":{"counter":10, "expires":100}}`, true, true, defaultGasForTests) @@ -3406,10 +3406,8 @@ func TestV1ReplyLoop(t *testing.T) { func TestBankMsgSend(t *testing.T) { for _, contract := range testContracts { t.Run(contract.CosmWasmVersion, func(t *testing.T) { - for _, callType := range []string{"init", "exec"} { t.Run(callType, func(t *testing.T) { - for _, test := range []struct { description string input string @@ -3422,50 +3420,50 @@ func TestBankMsgSend(t *testing.T) { description: "regular", input: `[{"amount":"2","denom":"denom"}]`, isSuccuss: true, - balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", - balancesAfter: "199998assaf,199998denom 5000assaf,5002denom", + balancesBefore: "5000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "4998assaf,199998denom 5000assaf,5002denom", }, { description: "multi-coin", input: `[{"amount":"1","denom":"assaf"},{"amount":"1","denom":"denom"}]`, isSuccuss: true, - balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", - balancesAfter: "199998assaf,199998denom 5001assaf,5001denom", + balancesBefore: "5000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "4998assaf,199998denom 5001assaf,5001denom", }, { description: "zero", input: `[{"amount":"0","denom":"denom"}]`, isSuccuss: false, errorMsg: "encrypted: dispatch: submessages: 0denom: invalid coins", - balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", - balancesAfter: "199998assaf,199998denom 5000assaf,5000denom", + balancesBefore: "5000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "4998assaf,199998denom 5000assaf,5000denom", }, { description: "insufficient funds", input: `[{"amount":"3","denom":"denom"}]`, isSuccuss: false, - balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", - balancesAfter: "199998assaf,199998denom 5000assaf,5000denom", + balancesBefore: "5000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "4998assaf,199998denom 5000assaf,5000denom", errorMsg: "encrypted: dispatch: submessages: 2denom is smaller than 3denom: insufficient funds", }, { description: "non-existing denom", input: `[{"amount":"1","denom":"blabla"}]`, isSuccuss: false, - balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", - balancesAfter: "199998assaf,199998denom 5000assaf,5000denom", + balancesBefore: "5000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "4998assaf,199998denom 5000assaf,5000denom", errorMsg: "encrypted: dispatch: submessages: 0blabla is smaller than 1blabla: insufficient funds", }, { description: "none", input: `[]`, isSuccuss: true, - balancesBefore: "200000assaf,200000denom 5000assaf,5000denom", - balancesAfter: "199998assaf,199998denom 5000assaf,5000denom", + balancesBefore: "5000assaf,200000denom 5000assaf,5000denom", + balancesAfter: "4998assaf,199998denom 5000assaf,5000denom", }, } { t.Run(test.description, func(t *testing.T) { - ctx, keeper, codeID, _, walletA, privKeyA, walletB, _ := setupTest(t, contract.WasmFilePath) + ctx, keeper, codeID, _, walletA, privKeyA, walletB, _ := setupTest(t, contract.WasmFilePath, sdk.NewCoins(sdk.NewInt64Coin("assaf", 5000))) walletACoinsBefore := keeper.bankKeeper.GetAllBalances(ctx, walletA) walletBCoinsBefore := keeper.bankKeeper.GetAllBalances(ctx, walletB) From 3c11d48cc16bc35d902f0b5e569ac3674e0aa7f4 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 12 Jul 2022 16:45:05 +0300 Subject: [PATCH 04/16] Fix typo in error message after V010MsgsToV1SubMsgs() --- x/compute/internal/keeper/keeper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/compute/internal/keeper/keeper.go b/x/compute/internal/keeper/keeper.go index 459dab479..ce990e4fe 100644 --- a/x/compute/internal/keeper/keeper.go +++ b/x/compute/internal/keeper/keeper.go @@ -471,7 +471,7 @@ func (k Keeper) Instantiate(ctx sdk.Context, codeID uint64, creator sdk.AccAddre subMessages, err := V010MsgsToV1SubMsgs(contractAddress.String(), res.Messages) if err != nil { - return nil, nil, sdkerrors.Wrap(err, "couldn't convert v010 messages to v1 messages") + return nil, nil, sdkerrors.Wrap(err, "couldn't convert v0.10 messages to v1 messages") } data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, subMessages, res.Log, []v1wasmTypes.Event{}, res.Data, initMsg, verificationInfo, wasmTypes.CosmosMsgVersionV010) From 98402cbbb6ecd6a4baf1dbeaa2dfd2c7d9e46e4b Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 12 Jul 2022 16:45:17 +0300 Subject: [PATCH 05/16] TestV010BankMsgSendFrom --- .../internal/keeper/secret_contracts_test.go | 22 +++++++++++++++++++ .../testdata/test-contract/src/contract.rs | 14 ++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/x/compute/internal/keeper/secret_contracts_test.go b/x/compute/internal/keeper/secret_contracts_test.go index a36aa24b2..b8992f796 100644 --- a/x/compute/internal/keeper/secret_contracts_test.go +++ b/x/compute/internal/keeper/secret_contracts_test.go @@ -3403,6 +3403,28 @@ func TestV1ReplyLoop(t *testing.T) { require.Equal(t, uint32(20), binary.BigEndian.Uint32(data)) } +func TestV010BankMsgSendFrom(t *testing.T) { + for _, callType := range []string{"init", "exec"} { + t.Run(callType, func(t *testing.T) { + ctx, keeper, codeID, _, walletA, privKeyA, walletB, _ := setupTest(t, "./testdata/test-contract/contract.wasm", sdk.NewCoins()) + + var err cosmwasm.StdError + var contractAddress sdk.AccAddress + + if callType == "init" { + contractAddress, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, fmt.Sprintf(`{"bank_msg":{"to":"%s","from":"%s","amount":[{"amount":"1","denom":"denom"}]}}`, walletB.String(), walletA.String()), false, false, defaultGasForTests, -1, sdk.NewCoins()) + } else { + contractAddress, _, err = initHelperImpl(t, keeper, ctx, codeID, walletA, privKeyA, `{"nop":{}}`, false, false, defaultGasForTests, -1, sdk.NewCoins()) + + _, _, _, err = execHelper(t, keeper, ctx, contractAddress, walletA, privKeyA, fmt.Sprintf(`{"bank_msg":{"to":"%s","from":"%s","amount":[{"amount":"1","denom":"denom"}]}}`, walletB.String(), walletA.String()), false, false, math.MaxUint64, 0) + } + + require.NotEmpty(t, err) + require.Contains(t, err.Error(), "contract doesn't have permission to send funds from another account") + }) + } +} + func TestBankMsgSend(t *testing.T) { for _, contract := range testContracts { t.Run(contract.CosmWasmVersion, func(t *testing.T) { diff --git a/x/compute/internal/keeper/testdata/test-contract/src/contract.rs b/x/compute/internal/keeper/testdata/test-contract/src/contract.rs index 6c25f3019..ebb663ad0 100644 --- a/x/compute/internal/keeper/testdata/test-contract/src/contract.rs +++ b/x/compute/internal/keeper/testdata/test-contract/src/contract.rs @@ -76,6 +76,7 @@ pub enum InitMsg { BankMsg { amount: Vec, to: HumanAddr, + from: Option, }, } @@ -171,6 +172,7 @@ pub enum HandleMsg { BankMsg { amount: Vec, to: HumanAddr, + from: Option, }, SendFundsToInitCallback { amount: u32, @@ -417,9 +419,13 @@ pub fn init( log: vec![], }) } - InitMsg::BankMsg { to, amount: coins } => Ok(InitResponse { + InitMsg::BankMsg { + to, + amount: coins, + from, + } => Ok(InitResponse { messages: vec![CosmosMsg::Bank(BankMsg::Send { - from_address: env.contract.address, + from_address: from.unwrap_or(env.contract.address), to_address: to, amount: coins, })], @@ -638,9 +644,9 @@ pub fn handle( log: vec![], data: None, }), - HandleMsg::BankMsg { to, amount } => Ok(HandleResponse { + HandleMsg::BankMsg { to, amount, from } => Ok(HandleResponse { messages: vec![CosmosMsg::Bank(BankMsg::Send { - from_address: env.contract.address, + from_address: from.unwrap_or(env.contract.address), to_address: to, amount, })], From 3f92955fc3672720f432c1d5d7a189079925ece5 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 12 Jul 2022 17:43:25 +0300 Subject: [PATCH 06/16] Fix clippy --- .../src/contract_operations.rs | 125 ++++++++---------- .../src/contract_validation.rs | 28 +++- .../enclaves/shared/contract-engine/src/io.rs | 49 ++++--- 3 files changed, 107 insertions(+), 95 deletions(-) diff --git a/cosmwasm/enclaves/shared/contract-engine/src/contract_operations.rs b/cosmwasm/enclaves/shared/contract-engine/src/contract_operations.rs index e2eeee296..838e3fa7c 100644 --- a/cosmwasm/enclaves/shared/contract-engine/src/contract_operations.rs +++ b/cosmwasm/enclaves/shared/contract-engine/src/contract_operations.rs @@ -2,6 +2,7 @@ use log::*; use enclave_ffi_types::{Ctx, EnclaveError}; +use crate::contract_validation::{ReplyParams, ValidatedMessage}; use crate::external::results::{HandleSuccess, InitSuccess, QuerySuccess}; use crate::wasm::CosmWasmApiVersion; use cosmos_proto::tx::signing::SignMode; @@ -108,7 +109,10 @@ pub fn init( let decrypted_msg = secret_msg.decrypt()?; - let (validated_msg, reply_params) = validate_msg(&decrypted_msg, contract_code.hash(), None)?; + let ValidatedMessage { + validated_msg, + reply_params, + } = validate_msg(&decrypted_msg, contract_code.hash(), None)?; trace!( "init input after decryption: {:?}", @@ -142,8 +146,7 @@ pub fn init( // TODO: ref: https://github.com/CosmWasm/cosmwasm/blob/b971c037a773bf6a5f5d08a88485113d9b9e8e7b/packages/std/src/query.rs#L13 let output = encrypt_output( output, - secret_msg.nonce, - secret_msg.user_public_key, + &secret_msg, &canonical_contract_address, &env_v010.contract_code_hash, reply_params, @@ -167,25 +170,14 @@ pub fn init( }) } -pub struct TaggedBool { - b: bool, +pub struct ParsedMessage { + pub should_validate_sig_info: bool, + pub was_msg_encrypted: bool, + pub secret_msg: SecretMessage, + pub decrypted_msg: Vec, + pub contract_hash_for_validation: Option>, } -impl From for TaggedBool { - fn from(b: bool) -> Self { - TaggedBool { b } - } -} - -impl Into for TaggedBool { - fn into(self) -> bool { - self.b - } -} - -type ShouldValidateSigInfo = TaggedBool; -type WasMessageEncrypted = TaggedBool; - pub fn reduct_custom_events(reply: &mut Reply) { reply.result = match &reply.result { SubMsgResult::Ok(r) => { @@ -228,16 +220,7 @@ pub fn parse_message( message: &[u8], sig_info: &SigInfo, handle_type: &HandleType, -) -> Result< - ( - ShouldValidateSigInfo, - WasMessageEncrypted, - SecretMessage, - Vec, - Option>, - ), - EnclaveError, -> { +) -> Result { let orig_secret_msg = SecretMessage::from_slice(message)?; return match handle_type { @@ -247,13 +230,13 @@ pub fn parse_message( base64::encode(&message) ); let decrypted_msg = orig_secret_msg.decrypt()?; - Ok(( - ShouldValidateSigInfo::from(true), - WasMessageEncrypted::from(true), - orig_secret_msg, + Ok(ParsedMessage { + should_validate_sig_info: true, + was_msg_encrypted: true, + secret_msg: orig_secret_msg, decrypted_msg, - None, - )) + contract_hash_for_validation: None, + }) } HandleType::HANDLE_TYPE_REPLY => { @@ -315,13 +298,13 @@ pub fn parse_message( EnclaveError::FailedToSerialize })?; - return Ok(( - ShouldValidateSigInfo::from(false), - WasMessageEncrypted::from(false), - reply_secret_msg, - serialized_reply, - None, - )); + return Ok(ParsedMessage { + should_validate_sig_info: false, + was_msg_encrypted: false, + secret_msg: reply_secret_msg, + decrypted_msg: serialized_reply, + contract_hash_for_validation: None, + }); } // Here we are sure the reply is OK because only OK is encrypted @@ -420,13 +403,15 @@ pub fn parse_message( msg: serialized_encrypted_reply, }; - Ok(( - ShouldValidateSigInfo::from(true), - WasMessageEncrypted::from(true), - reply_secret_msg, - decrypted_reply_as_vec, - Some(tmp_decrypted_msg_id[..HEX_ENCODED_HASH_SIZE].to_vec()), - )) + Ok(ParsedMessage { + should_validate_sig_info: true, + was_msg_encrypted: true, + secret_msg: reply_secret_msg, + decrypted_msg: decrypted_reply_as_vec, + contract_hash_for_validation: Some( + tmp_decrypted_msg_id[..HEX_ENCODED_HASH_SIZE].to_vec(), + ), + }) } SubMsgResult::Err(response) => { let secret_msg = SecretMessage { @@ -511,19 +496,22 @@ pub fn parse_message( msg: serialized_encrypted_reply, }; - Ok(( - ShouldValidateSigInfo::from(true), - WasMessageEncrypted::from(true), - reply_secret_msg, - decrypted_reply_as_vec, - Some(tmp_decrypted_msg_id[..HEX_ENCODED_HASH_SIZE].to_vec()), - )) + Ok(ParsedMessage { + should_validate_sig_info: true, + was_msg_encrypted: true, + secret_msg: reply_secret_msg, + decrypted_msg: decrypted_reply_as_vec, + contract_hash_for_validation: Some( + tmp_decrypted_msg_id[..HEX_ENCODED_HASH_SIZE].to_vec(), + ), + }) } } } }; } +#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))] pub fn handle( context: Ctx, gas_limit: u64, @@ -584,33 +572,33 @@ pub fn handle( // When the message is handle, we expect it always to be encrypted while in Reply for example it might be plaintext let parsed_handle_type = HandleType::try_from(handle_type)?; - let ( + let ParsedMessage { should_validate_sig_info, was_msg_encrypted, secret_msg, decrypted_msg, contract_hash_for_validation, - ) = parse_message(msg, &parsed_sig_info, &parsed_handle_type)?; + } = parse_message(msg, &parsed_sig_info, &parsed_handle_type)?; // There is no signature to verify when the input isn't signed. // Receiving unsigned messages is only possible in Handle. (Init tx are always signed) // All of these functions go through handle but the data isn't signed: // Reply (that is not WASM reply) - if should_validate_sig_info.into() { + if should_validate_sig_info { // Verify env parameters against the signed tx verify_params(&parsed_sig_info, &env_v010, &secret_msg)?; } let mut validated_msg = decrypted_msg.clone(); - let mut reply_params: Option<(Vec, u64)> = None; - if was_msg_encrypted.into() { + let mut reply_params: Option = None; + if was_msg_encrypted { let x = validate_msg( &decrypted_msg, contract_code.hash(), contract_hash_for_validation, )?; - validated_msg = x.0; - reply_params = x.1; + validated_msg = x.validated_msg; + reply_params = x.reply_params; } trace!( @@ -656,8 +644,7 @@ pub fn handle( let output = encrypt_output( output, - secret_msg.nonce, - secret_msg.user_public_key, + &secret_msg, &canonical_contract_address, &env_v010.contract_code_hash, reply_params, @@ -722,7 +709,8 @@ pub fn query( "query input afer decryption: {:?}", String::from_utf8_lossy(&decrypted_msg) ); - let validated_msg = validate_msg(&decrypted_msg, contract_code.hash(), None)?.0; + let ValidatedMessage { validated_msg, .. } = + validate_msg(&decrypted_msg, contract_code.hash(), None)?; let mut engine = start_engine( context, @@ -749,8 +737,7 @@ pub fn query( let output = encrypt_output( output, - secret_msg.nonce, - secret_msg.user_public_key, + &secret_msg, &CanonicalAddr(Binary(Vec::new())), // Not used for queries (can't init a new contract from a query) &"".to_string(), // Not used for queries (can't call a sub-message from a query), None, // Not used for queries (Query response is not replied to the caller), diff --git a/cosmwasm/enclaves/shared/contract-engine/src/contract_validation.rs b/cosmwasm/enclaves/shared/contract-engine/src/contract_validation.rs index 3dec8bd74..77c30f2c0 100644 --- a/cosmwasm/enclaves/shared/contract-engine/src/contract_validation.rs +++ b/cosmwasm/enclaves/shared/contract-engine/src/contract_validation.rs @@ -133,12 +133,22 @@ pub fn validate_contract_key( calculated_authentication_id == expected_authentication_id } +pub struct ValidatedMessage { + pub validated_msg: Vec, + pub reply_params: Option, +} + +pub struct ReplyParams { + pub recipient_contract_hash: Vec, + pub sub_msg_id: u64, +} + /// Validate that the message sent to the enclave (after decryption) was actually addressed to this contract. pub fn validate_msg( msg: &[u8], contract_hash: [u8; HASH_SIZE], contract_hash_for_validation: Option>, -) -> Result<(Vec, Option<(Vec, u64)>), EnclaveError> { +) -> Result { if contract_hash_for_validation.is_none() && msg.len() < HEX_ENCODED_HASH_SIZE { warn!("Malformed message - expected contract code hash to be prepended to the msg"); return Err(EnclaveError::ValidationFailure); @@ -182,13 +192,19 @@ pub fn validate_msg( let mut reply_recipient_contract_hash: [u8; HEX_ENCODED_HASH_SIZE] = [0u8; HEX_ENCODED_HASH_SIZE]; reply_recipient_contract_hash.copy_from_slice(&validated_msg[0..HEX_ENCODED_HASH_SIZE]); - return Ok(( - validated_msg[HEX_ENCODED_HASH_SIZE..].to_vec(), - Some((reply_recipient_contract_hash.to_vec(), sub_msg_id)), - )); + return Ok(ValidatedMessage { + validated_msg: validated_msg[HEX_ENCODED_HASH_SIZE..].to_vec(), + reply_params: Some(ReplyParams { + recipient_contract_hash: reply_recipient_contract_hash.to_vec(), + sub_msg_id, + }), + }); } - Ok((validated_msg, None)) + Ok(ValidatedMessage { + validated_msg, + reply_params: None, + }) } /// Verify all the parameters sent to the enclave match up, and were signed by the right account. diff --git a/cosmwasm/enclaves/shared/contract-engine/src/io.rs b/cosmwasm/enclaves/shared/contract-engine/src/io.rs index c6e302331..8d691b98b 100644 --- a/cosmwasm/enclaves/shared/contract-engine/src/io.rs +++ b/cosmwasm/enclaves/shared/contract-engine/src/io.rs @@ -1,3 +1,5 @@ +use crate::contract_validation::ReplyParams; + /// This contains all the user-facing functions. In these functions we will be using /// the consensus_io_exchange_keypair and a user-generated key to create a symmetric key /// that is unique to the user and the enclave @@ -101,7 +103,7 @@ pub fn calc_encryption_key(nonce: &IoNonce, user_public_key: &Ed25519PublicKey) fn encrypt_serializable( key: &AESKey, val: &T, - reply_params: &Option<(Vec, u64)>, + reply_params: &Option, ) -> Result where T: ?Sized + Serialize, @@ -122,12 +124,15 @@ where fn encrypt_preserialized_string( key: &AESKey, val: &str, - reply_params: &Option<(Vec, u64)>, + reply_params: &Option, ) -> Result { let serialized = match reply_params { - Some((reply_recipient_contract_hash, _)) => { + Some(ReplyParams { + recipient_contract_hash, + .. + }) => { let mut ser = vec![]; - ser.extend_from_slice(&reply_recipient_contract_hash); + ser.extend_from_slice(&recipient_contract_hash); ser.extend_from_slice(val.as_bytes()); ser } @@ -152,18 +157,17 @@ fn b64_encode(data: &[u8]) -> String { pub fn encrypt_output( output: Vec, - nonce: IoNonce, - user_public_key: Ed25519PublicKey, + secret_msg: &SecretMessage, contract_addr: &CanonicalAddr, contract_hash: &str, - reply_params: Option<(Vec, u64)>, + reply_params: Option, sender_addr: &CanonicalAddr, is_query_output: bool, ) -> Result, EnclaveError> { // When encrypting an output we might encrypt an output that is a reply to a caller contract (Via "Reply" endpoint). // Therefore if reply_recipient_contract_hash is not "None" we append it to any encrypted data besided submessages that are irrelevant for replies. // More info in: https://github.com/CosmWasm/cosmwasm/blob/v1.0.0/packages/std/src/results/submessages.rs#L192-L198 - let encryption_key = calc_encryption_key(&nonce, &user_public_key); + let encryption_key = calc_encryption_key(&secret_msg.nonce, &secret_msg.user_public_key); trace!( "Output before encryption: {:?}", String::from_utf8_lossy(&output) @@ -190,7 +194,7 @@ pub fn encrypt_output( Some(ref r) => { let encrypted_id = Binary::from_base64(&encrypt_preserialized_string( &encryption_key, - &r.1.to_string(), + &r.sub_msg_id.to_string(), &reply_params, )?)?; @@ -215,8 +219,8 @@ pub fn encrypt_output( EnclaveError::FailedToSerialize })?; let tmp_secret_msg = SecretMessage { - nonce, - user_public_key, + nonce: secret_msg.nonce, + user_public_key: secret_msg.user_public_key, msg: reply_as_vec, }; @@ -240,7 +244,12 @@ pub fn encrypt_output( } => { for msg in &mut ok.messages { if let cosmwasm_v010_types::types::CosmosMsg::Wasm(wasm_msg) = msg { - encrypt_v010_wasm_msg(wasm_msg, nonce, user_public_key, contract_addr)?; + encrypt_v010_wasm_msg( + wasm_msg, + secret_msg.nonce, + secret_msg.user_public_key, + contract_addr, + )?; } } @@ -263,7 +272,7 @@ pub fn encrypt_output( Some(ref r) => { let encrypted_id = Binary::from_base64(&encrypt_preserialized_string( &encryption_key, - &r.1.to_string(), + &r.sub_msg_id.to_string(), &reply_params, )?)?; @@ -295,8 +304,8 @@ pub fn encrypt_output( EnclaveError::FailedToSerialize })?; let tmp_secret_msg = SecretMessage { - nonce, - user_public_key, + nonce: secret_msg.nonce, + user_public_key: secret_msg.user_public_key, msg: reply_as_vec, }; @@ -320,8 +329,8 @@ pub fn encrypt_output( wasm_msg, &sub_msg.reply_on, sub_msg.id, - nonce, - user_public_key, + secret_msg.nonce, + secret_msg.user_public_key, contract_addr, contract_hash, )?; @@ -361,7 +370,7 @@ pub fn encrypt_output( Some(ref r) => { let encrypted_id = Binary::from_base64(&encrypt_preserialized_string( &encryption_key, - &r.1.to_string(), + &r.sub_msg_id.to_string(), &reply_params, )?)?; @@ -389,8 +398,8 @@ pub fn encrypt_output( EnclaveError::FailedToSerialize })?; let tmp_secret_msg = SecretMessage { - nonce, - user_public_key, + nonce: secret_msg.nonce, + user_public_key: secret_msg.user_public_key, msg: reply_as_vec, }; From 3a96db396b05c9dd394779c960f3648d6d38d35b Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 12 Jul 2022 17:47:14 +0300 Subject: [PATCH 07/16] Fix clippy? --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a1a661411..162562965 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -251,6 +251,7 @@ jobs: source "$HOME/.sgxsdk/sgxsdk/environment" make vendor cd cosmwasm/enclaves/execute/ + rustup component add rust-src SGX_MODE=SW make clippy SGX_MODE=HW make clippy From 03bfae0d0ba0bcae217205be33005610ab8592f9 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 12 Jul 2022 18:14:13 +0300 Subject: [PATCH 08/16] Fix clippy? --- .github/workflows/ci.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 162562965..7903308d9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -234,9 +234,12 @@ jobs: with: path: ~/.cache/sccache key: ${{ runner.os }}-sccache - - run: rustup component add rust-src clippy + - run: | + cd cosmwasm/enclaves/execute/ + rustup component add rust-src clippy - name: Install xargo run: | + cd cosmwasm/enclaves/execute/ cargo --version rustc --version cargo +stable install xargo --version 0.3.25 @@ -251,7 +254,6 @@ jobs: source "$HOME/.sgxsdk/sgxsdk/environment" make vendor cd cosmwasm/enclaves/execute/ - rustup component add rust-src SGX_MODE=SW make clippy SGX_MODE=HW make clippy From 43baefab32c951f0e4d1ff6daad4a8702a8cc7a8 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 12 Jul 2022 18:20:05 +0300 Subject: [PATCH 09/16] Fix CI? --- .github/workflows/ci.yaml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7903308d9..52231c2e3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -30,7 +30,10 @@ jobs: with: path: ~/.cache/sccache key: ${{ runner.os }}-sccache - - run: rustup component add rust-src clippy + - run: | + rustup component add rust-src clippy + cd cosmwasm/enclaves/execute/ + rustup component add rust-src clippy - name: Install xargo run: | cargo --version @@ -80,7 +83,10 @@ jobs: with: path: ~/.cache/sccache key: ${{ runner.os }}-sccache - - run: rustup component add rust-src clippy + - run: | + rustup component add rust-src clippy + cd cosmwasm/enclaves/execute/ + rustup component add rust-src clippy - name: Install xargo run: | cargo --version @@ -235,6 +241,7 @@ jobs: path: ~/.cache/sccache key: ${{ runner.os }}-sccache - run: | + rustup component add rust-src clippy cd cosmwasm/enclaves/execute/ rustup component add rust-src clippy - name: Install xargo From e6ca6670637c56458a1b9940aab9221e208595b1 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 12 Jul 2022 22:19:37 +0300 Subject: [PATCH 10/16] Go tests: Fix %w in fmt.Sprintf --- x/compute/client/rest/query.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/compute/client/rest/query.go b/x/compute/client/rest/query.go index 89b79e2de..8006f23c2 100644 --- a/x/compute/client/rest/query.go +++ b/x/compute/client/rest/query.go @@ -267,7 +267,7 @@ func queryCodeHashHandlerFn(cliCtx client.Context) http.HandlerFunc { err = json.Unmarshal(res, &codeResp) if err != nil { - rest.WriteErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("cannot parse as CodeResponse: %w", err)) + rest.WriteErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("cannot parse as CodeResponse: %s", err.Error())) return } From bf272922e09c68a65c8e261bb85fc7e0c2e8912f Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Jul 2022 09:10:33 +0300 Subject: [PATCH 11/16] cargo update v1 test contract --- .../testdata/v1-sanity-contract/Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/x/compute/internal/keeper/testdata/v1-sanity-contract/Cargo.lock b/x/compute/internal/keeper/testdata/v1-sanity-contract/Cargo.lock index 0afe44cf8..b5eb2fefa 100644 --- a/x/compute/internal/keeper/testdata/v1-sanity-contract/Cargo.lock +++ b/x/compute/internal/keeper/testdata/v1-sanity-contract/Cargo.lock @@ -56,7 +56,7 @@ checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" [[package]] name = "cosmwasm-crypto" version = "1.0.0" -source = "git+https://github.com/scrtlabs/cosmwasm?branch=secret#ae7272784f38fd58a4065d194a91cc9b4f5e5fa7" +source = "git+https://github.com/scrtlabs/cosmwasm?branch=secret#4acae6ac8182b7629aa0f58cdab73fcec1305a48" dependencies = [ "digest", "ed25519-zebra", @@ -68,7 +68,7 @@ dependencies = [ [[package]] name = "cosmwasm-derive" version = "1.0.0" -source = "git+https://github.com/scrtlabs/cosmwasm?branch=secret#ae7272784f38fd58a4065d194a91cc9b4f5e5fa7" +source = "git+https://github.com/scrtlabs/cosmwasm?branch=secret#4acae6ac8182b7629aa0f58cdab73fcec1305a48" dependencies = [ "syn", ] @@ -76,7 +76,7 @@ dependencies = [ [[package]] name = "cosmwasm-std" version = "1.0.0" -source = "git+https://github.com/scrtlabs/cosmwasm?branch=secret#ae7272784f38fd58a4065d194a91cc9b4f5e5fa7" +source = "git+https://github.com/scrtlabs/cosmwasm?branch=secret#4acae6ac8182b7629aa0f58cdab73fcec1305a48" dependencies = [ "base64", "cosmwasm-crypto", @@ -92,7 +92,7 @@ dependencies = [ [[package]] name = "cosmwasm-storage" version = "1.0.0" -source = "git+https://github.com/scrtlabs/cosmwasm?branch=secret#ae7272784f38fd58a4065d194a91cc9b4f5e5fa7" +source = "git+https://github.com/scrtlabs/cosmwasm?branch=secret#4acae6ac8182b7629aa0f58cdab73fcec1305a48" dependencies = [ "cosmwasm-std", "serde", @@ -467,9 +467,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.138" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" +checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6" dependencies = [ "serde_derive", ] @@ -494,9 +494,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.138" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" +checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" dependencies = [ "proc-macro2", "quote", From 0087aafd14a208050e95fc9469070a45e9026aed Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Jul 2022 09:13:09 +0300 Subject: [PATCH 12/16] Fix CI? Didn't compile v1-sanity-contract until now --- .github/workflows/ci.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 52231c2e3..cf277eef5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -154,6 +154,10 @@ jobs: with: name: static-too-high-initial-memory.wasm path: ./x/compute/internal/keeper/testdata/test-contract/static-too-high-initial-memory.wasm + - uses: actions/upload-artifact@v2 + with: + name: v1-contract.wasm + path: ./x/compute/internal/keeper/testdata/v1-sanity-contract/contract.wasm Go-Tests: runs-on: ubuntu-20.04 @@ -189,11 +193,15 @@ jobs: - uses: actions/download-artifact@v2 with: name: static-too-high-initial-memory.wasm + - uses: actions/download-artifact@v2 + with: + name: v1-contract.wasm - name: Setup Files run: | cp libgo_cosmwasm.so ./go-cosmwasm/api/libgo_cosmwasm.so cp librust_cosmwasm_enclave.signed.so ./go-cosmwasm/librust_cosmwasm_enclave.signed.so cp contract.wasm ./x/compute/internal/keeper/testdata/test-contract/contract.wasm + cp v1-contract.wasm ./x/compute/internal/keeper/testdata/v1-sanity-contract/contract.wasm cp too-high-initial-memory.wasm ./x/compute/internal/keeper/testdata/test-contract/too-high-initial-memory.wasm cp contract_with_floats.wasm ./x/compute/internal/keeper/testdata/test-contract/contract_with_floats.wasm cp static-too-high-initial-memory.wasm ./x/compute/internal/keeper/testdata/test-contract/static-too-high-initial-memory.wasm From 1e667be6fdc90462cd48d8b89b96f889be4a4276 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Jul 2022 09:37:06 +0300 Subject: [PATCH 13/16] CI: Add debug prints to help fix the CI --- .github/workflows/ci.yaml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index cf277eef5..11652d4cf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -134,6 +134,10 @@ jobs: with: name: contract.wasm path: ./x/compute/internal/keeper/testdata/test-contract/contract.wasm + - uses: actions/upload-artifact@v2 + with: + name: v1-contract.wasm + path: ./x/compute/internal/keeper/testdata/v1-sanity-contract/contract.wasm - uses: actions/upload-artifact@v2 with: name: enclave @@ -154,10 +158,6 @@ jobs: with: name: static-too-high-initial-memory.wasm path: ./x/compute/internal/keeper/testdata/test-contract/static-too-high-initial-memory.wasm - - uses: actions/upload-artifact@v2 - with: - name: v1-contract.wasm - path: ./x/compute/internal/keeper/testdata/v1-sanity-contract/contract.wasm Go-Tests: runs-on: ubuntu-20.04 @@ -184,6 +184,9 @@ jobs: - uses: actions/download-artifact@v2 with: name: contract.wasm + - uses: actions/download-artifact@v2 + with: + name: v1-contract.wasm - uses: actions/download-artifact@v2 with: name: contract_with_floats.wasm @@ -193,11 +196,9 @@ jobs: - uses: actions/download-artifact@v2 with: name: static-too-high-initial-memory.wasm - - uses: actions/download-artifact@v2 - with: - name: v1-contract.wasm - name: Setup Files run: | + find -name \*.wasm cp libgo_cosmwasm.so ./go-cosmwasm/api/libgo_cosmwasm.so cp librust_cosmwasm_enclave.signed.so ./go-cosmwasm/librust_cosmwasm_enclave.signed.so cp contract.wasm ./x/compute/internal/keeper/testdata/test-contract/contract.wasm @@ -205,6 +206,7 @@ jobs: cp too-high-initial-memory.wasm ./x/compute/internal/keeper/testdata/test-contract/too-high-initial-memory.wasm cp contract_with_floats.wasm ./x/compute/internal/keeper/testdata/test-contract/contract_with_floats.wasm cp static-too-high-initial-memory.wasm ./x/compute/internal/keeper/testdata/test-contract/static-too-high-initial-memory.wasm + find -name \*.wasm - name: Test x/registration run: | source "$HOME/.sgxsdk/sgxsdk/environment" From 192dc19746ba947459388b120544de67b885ea83 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Jul 2022 10:38:48 +0300 Subject: [PATCH 14/16] CI debug print --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 11652d4cf..5ad5beaf1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -198,7 +198,7 @@ jobs: name: static-too-high-initial-memory.wasm - name: Setup Files run: | - find -name \*.wasm + find "$(pwd)" -name \*.wasm cp libgo_cosmwasm.so ./go-cosmwasm/api/libgo_cosmwasm.so cp librust_cosmwasm_enclave.signed.so ./go-cosmwasm/librust_cosmwasm_enclave.signed.so cp contract.wasm ./x/compute/internal/keeper/testdata/test-contract/contract.wasm @@ -206,7 +206,7 @@ jobs: cp too-high-initial-memory.wasm ./x/compute/internal/keeper/testdata/test-contract/too-high-initial-memory.wasm cp contract_with_floats.wasm ./x/compute/internal/keeper/testdata/test-contract/contract_with_floats.wasm cp static-too-high-initial-memory.wasm ./x/compute/internal/keeper/testdata/test-contract/static-too-high-initial-memory.wasm - find -name \*.wasm + find "$(pwd)" -name \*.wasm - name: Test x/registration run: | source "$HOME/.sgxsdk/sgxsdk/environment" From ec726217dcae07c2ed4a6a3450fc6cf32fb9a710 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Jul 2022 11:21:55 +0300 Subject: [PATCH 15/16] Fix CI? --- .github/workflows/ci.yaml | 2 +- .../keeper/testdata/v1-sanity-contract.wasm | Bin 167117 -> 0 bytes 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100755 x/compute/internal/keeper/testdata/v1-sanity-contract.wasm diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5ad5beaf1..3e384815e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -187,6 +187,7 @@ jobs: - uses: actions/download-artifact@v2 with: name: v1-contract.wasm + path: ./x/compute/internal/keeper/testdata/v1-sanity-contract/contract.wasm - uses: actions/download-artifact@v2 with: name: contract_with_floats.wasm @@ -202,7 +203,6 @@ jobs: cp libgo_cosmwasm.so ./go-cosmwasm/api/libgo_cosmwasm.so cp librust_cosmwasm_enclave.signed.so ./go-cosmwasm/librust_cosmwasm_enclave.signed.so cp contract.wasm ./x/compute/internal/keeper/testdata/test-contract/contract.wasm - cp v1-contract.wasm ./x/compute/internal/keeper/testdata/v1-sanity-contract/contract.wasm cp too-high-initial-memory.wasm ./x/compute/internal/keeper/testdata/test-contract/too-high-initial-memory.wasm cp contract_with_floats.wasm ./x/compute/internal/keeper/testdata/test-contract/contract_with_floats.wasm cp static-too-high-initial-memory.wasm ./x/compute/internal/keeper/testdata/test-contract/static-too-high-initial-memory.wasm diff --git a/x/compute/internal/keeper/testdata/v1-sanity-contract.wasm b/x/compute/internal/keeper/testdata/v1-sanity-contract.wasm deleted file mode 100755 index fb86508ad596c9f5958951c155d4441e53669ca3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167117 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 From 453bbd56f1bf048175c35195ad9e663110b016de Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Jul 2022 13:15:55 +0300 Subject: [PATCH 16/16] Fix CI! --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3e384815e..97079d9df 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -187,7 +187,7 @@ jobs: - uses: actions/download-artifact@v2 with: name: v1-contract.wasm - path: ./x/compute/internal/keeper/testdata/v1-sanity-contract/contract.wasm + path: ./x/compute/internal/keeper/testdata/v1-sanity-contract - uses: actions/download-artifact@v2 with: name: contract_with_floats.wasm