From 67e05355d30fb607c8bddfd3c9575e853c3203d5 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 30 Jul 2020 10:46:48 +0200 Subject: [PATCH 1/6] Implement `From<&[u8]>` and `From>` for `CanonicalAddr` --- CHANGELOG.md | 1 + packages/std/src/types.rs | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea10883b8a..59ff2afa77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ via `into` or `try_into`. Option to simplify response construction. - Env uses `HumanAddr` for `message.sender` and `contract_address` - Remove `Api` argument from `mock_env` +- Implement `From<&[u8]>` and `From>` for `CanonicalAddr` **cosmwasm-vm** diff --git a/packages/std/src/types.rs b/packages/std/src/types.rs index 5948fc072b..0e9e52954e 100644 --- a/packages/std/src/types.rs +++ b/packages/std/src/types.rs @@ -10,9 +10,6 @@ use crate::encoding::Binary; #[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq, JsonSchema, Hash)] pub struct HumanAddr(pub String); -#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, JsonSchema)] -pub struct CanonicalAddr(pub Binary); - impl HumanAddr { pub fn as_str(&self) -> &str { &self.0 @@ -55,6 +52,21 @@ impl From for HumanAddr { } } +#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, JsonSchema)] +pub struct CanonicalAddr(pub Binary); + +impl From<&[u8]> for CanonicalAddr { + fn from(source: &[u8]) -> Self { + Self(source.into()) + } +} + +impl From> for CanonicalAddr { + fn from(source: Vec) -> Self { + Self(source.into()) + } +} + impl CanonicalAddr { pub fn as_slice(&self) -> &[u8] { &self.0.as_slice() From 0d93b0ac16896d90d111925124f6692b2c87263e Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 30 Jul 2020 11:07:25 +0200 Subject: [PATCH 2/6] Create addresses module for CanonicalAddr, HumanAddr --- packages/std/src/addresses.rs | 88 +++++++++++++++++++++++++++++++++ packages/std/src/imports.rs | 2 +- packages/std/src/init_handle.rs | 3 +- packages/std/src/lib.rs | 6 +-- packages/std/src/mock.rs | 3 +- packages/std/src/query.rs | 2 +- packages/std/src/traits.rs | 3 +- packages/std/src/types.rs | 83 +------------------------------ 8 files changed, 100 insertions(+), 90 deletions(-) create mode 100644 packages/std/src/addresses.rs diff --git a/packages/std/src/addresses.rs b/packages/std/src/addresses.rs new file mode 100644 index 0000000000..cba8fc089f --- /dev/null +++ b/packages/std/src/addresses.rs @@ -0,0 +1,88 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::fmt; + +use crate::encoding::Binary; + +// Added Eq and Hash to allow this to be a key in a HashMap (MockQuerier) +#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq, JsonSchema, Hash)] +pub struct HumanAddr(pub String); + +impl HumanAddr { + pub fn as_str(&self) -> &str { + &self.0 + } + + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +impl fmt::Display for HumanAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", &self.0) + } +} + +impl From<&str> for HumanAddr { + fn from(addr: &str) -> Self { + HumanAddr(addr.to_string()) + } +} + +impl From<&HumanAddr> for HumanAddr { + fn from(addr: &HumanAddr) -> Self { + HumanAddr(addr.0.to_string()) + } +} + +impl From<&&HumanAddr> for HumanAddr { + fn from(addr: &&HumanAddr) -> Self { + HumanAddr(addr.0.to_string()) + } +} + +impl From for HumanAddr { + fn from(addr: String) -> Self { + HumanAddr(addr) + } +} + +#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, JsonSchema)] +pub struct CanonicalAddr(pub Binary); + +impl From<&[u8]> for CanonicalAddr { + fn from(source: &[u8]) -> Self { + Self(source.into()) + } +} + +impl From> for CanonicalAddr { + fn from(source: Vec) -> Self { + Self(source.into()) + } +} + +impl CanonicalAddr { + pub fn as_slice(&self) -> &[u8] { + &self.0.as_slice() + } + + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +impl fmt::Display for CanonicalAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} diff --git a/packages/std/src/imports.rs b/packages/std/src/imports.rs index 00554a0e7c..a8d6c3e14d 100644 --- a/packages/std/src/imports.rs +++ b/packages/std/src/imports.rs @@ -1,5 +1,6 @@ use std::vec::Vec; +use crate::addresses::{CanonicalAddr, HumanAddr}; use crate::encoding::Binary; use crate::errors::{StdError, StdResult}; #[cfg(feature = "iterator")] @@ -7,7 +8,6 @@ use crate::iterator::{Order, KV}; use crate::memory::{alloc, build_region, consume_region, Region}; use crate::serde::from_slice; use crate::traits::{Api, Querier, QuerierResult, ReadonlyStorage, Storage}; -use crate::types::{CanonicalAddr, HumanAddr}; /// An upper bound for typical canonical address lengths (e.g. 20 in Cosmos SDK/Ethereum or 32 in Nano/Substrate) const CANONICAL_ADDRESS_BUFFER_LENGTH: usize = 32; diff --git a/packages/std/src/init_handle.rs b/packages/std/src/init_handle.rs index 823fb080e4..c21df3790f 100644 --- a/packages/std/src/init_handle.rs +++ b/packages/std/src/init_handle.rs @@ -5,10 +5,11 @@ use serde::{Deserialize, Serialize}; use std::convert::TryFrom; use std::fmt; +use crate::addresses::HumanAddr; use crate::coins::Coin; use crate::encoding::Binary; use crate::errors::{StdError, StdResult}; -use crate::types::{Empty, HumanAddr}; +use crate::types::Empty; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] diff --git a/packages/std/src/lib.rs b/packages/std/src/lib.rs index 5b0418c03b..0011a5b7ab 100644 --- a/packages/std/src/lib.rs +++ b/packages/std/src/lib.rs @@ -1,5 +1,6 @@ // Exposed on all platforms +mod addresses; mod coins; mod encoding; mod entry_points; @@ -14,6 +15,7 @@ mod storage; mod traits; mod types; +pub use crate::addresses::{CanonicalAddr, HumanAddr}; pub use crate::coins::{coin, coins, has_coins, Coin}; pub use crate::encoding::Binary; pub use crate::errors::{StdError, StdResult, SystemError, SystemResult}; @@ -32,9 +34,7 @@ pub use crate::query::{ pub use crate::serde::{from_binary, from_slice, to_binary, to_vec}; pub use crate::storage::MemoryStorage; pub use crate::traits::{Api, Extern, Querier, QuerierResult, ReadonlyStorage, Storage}; -pub use crate::types::{ - BlockInfo, CanonicalAddr, ContractInfo, Empty, Env, HumanAddr, MessageInfo, -}; +pub use crate::types::{BlockInfo, ContractInfo, Empty, Env, MessageInfo}; // Exposed in wasm build only diff --git a/packages/std/src/mock.rs b/packages/std/src/mock.rs index ad834621b7..7f4ec52161 100644 --- a/packages/std/src/mock.rs +++ b/packages/std/src/mock.rs @@ -1,6 +1,7 @@ use serde::de::DeserializeOwned; use std::collections::HashMap; +use crate::addresses::{CanonicalAddr, HumanAddr}; use crate::coins::Coin; use crate::encoding::Binary; use crate::errors::{StdError, StdResult, SystemError, SystemResult}; @@ -12,7 +13,7 @@ use crate::query::{ use crate::serde::{from_slice, to_binary}; use crate::storage::MemoryStorage; use crate::traits::{Api, Extern, Querier, QuerierResult}; -use crate::types::{BlockInfo, CanonicalAddr, ContractInfo, Empty, Env, HumanAddr, MessageInfo}; +use crate::types::{BlockInfo, ContractInfo, Empty, Env, MessageInfo}; pub const MOCK_CONTRACT_ADDR: &str = "cosmos2contract"; diff --git a/packages/std/src/query.rs b/packages/std/src/query.rs index 722856be8c..70ca2b0033 100644 --- a/packages/std/src/query.rs +++ b/packages/std/src/query.rs @@ -2,11 +2,11 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt; +use crate::addresses::HumanAddr; use crate::coins::Coin; use crate::encoding::Binary; use crate::errors::StdResult; use crate::math::Decimal; -use crate::types::HumanAddr; pub type QueryResponse = Binary; diff --git a/packages/std/src/traits.rs b/packages/std/src/traits.rs index bfebb59f72..98bb1e5b44 100644 --- a/packages/std/src/traits.rs +++ b/packages/std/src/traits.rs @@ -1,5 +1,6 @@ use serde::{de::DeserializeOwned, Serialize}; +use crate::addresses::{CanonicalAddr, HumanAddr}; use crate::coins::Coin; use crate::encoding::Binary; use crate::errors::{StdError, StdResult, SystemResult}; @@ -12,7 +13,7 @@ use crate::query::{ StakingQuery, Validator, ValidatorsResponse, }; use crate::serde::{from_binary, to_vec}; -use crate::types::{CanonicalAddr, Empty, HumanAddr}; +use crate::types::Empty; /// Holds all external dependencies of the contract. /// Designed to allow easy dependency injection at runtime. diff --git a/packages/std/src/types.rs b/packages/std/src/types.rs index 0e9e52954e..9f368deb4a 100644 --- a/packages/std/src/types.rs +++ b/packages/std/src/types.rs @@ -1,89 +1,8 @@ -use std::fmt; - use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use crate::addresses::HumanAddr; use crate::coins::Coin; -use crate::encoding::Binary; - -// Added Eq and Hash to allow this to be a key in a HashMap (MockQuerier) -#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq, JsonSchema, Hash)] -pub struct HumanAddr(pub String); - -impl HumanAddr { - pub fn as_str(&self) -> &str { - &self.0 - } - pub fn len(&self) -> usize { - self.0.len() - } - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -impl fmt::Display for HumanAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", &self.0) - } -} - -impl From<&str> for HumanAddr { - fn from(addr: &str) -> Self { - HumanAddr(addr.to_string()) - } -} - -impl From<&HumanAddr> for HumanAddr { - fn from(addr: &HumanAddr) -> Self { - HumanAddr(addr.0.to_string()) - } -} - -impl From<&&HumanAddr> for HumanAddr { - fn from(addr: &&HumanAddr) -> Self { - HumanAddr(addr.0.to_string()) - } -} - -impl From for HumanAddr { - fn from(addr: String) -> Self { - HumanAddr(addr) - } -} - -#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, JsonSchema)] -pub struct CanonicalAddr(pub Binary); - -impl From<&[u8]> for CanonicalAddr { - fn from(source: &[u8]) -> Self { - Self(source.into()) - } -} - -impl From> for CanonicalAddr { - fn from(source: Vec) -> Self { - Self(source.into()) - } -} - -impl CanonicalAddr { - pub fn as_slice(&self) -> &[u8] { - &self.0.as_slice() - } - pub fn len(&self) -> usize { - self.0.len() - } - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -impl fmt::Display for CanonicalAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} #[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, JsonSchema)] pub struct Env { From 030ebe636c889d40b1fae5edebfa7007aed4ff06 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 30 Jul 2020 11:10:35 +0200 Subject: [PATCH 3/6] Add HandleMsg::UserErrorsInApiCalls to hackatom --- contracts/hackatom/schema/handle_msg.json | 12 +++++ contracts/hackatom/src/contract.rs | 58 +++++++++++++++++++++++ contracts/hackatom/tests/integration.rs | 39 ++++++++++----- 3 files changed, 96 insertions(+), 13 deletions(-) diff --git a/contracts/hackatom/schema/handle_msg.json b/contracts/hackatom/schema/handle_msg.json index 32518d25b7..88aeaf646f 100644 --- a/contracts/hackatom/schema/handle_msg.json +++ b/contracts/hackatom/schema/handle_msg.json @@ -73,6 +73,18 @@ "type": "object" } } + }, + { + "description": "Starting with CosmWasm 0.10, some API calls return user errors back to the contract. This triggers such user errors, ensuring the transaction does not fail in the backend.", + "type": "object", + "required": [ + "user_errors_in_api_calls" + ], + "properties": { + "user_errors_in_api_calls": { + "type": "object" + } + } } ] } diff --git a/contracts/hackatom/src/contract.rs b/contracts/hackatom/src/contract.rs index 4dd92df57b..e093369d80 100644 --- a/contracts/hackatom/src/contract.rs +++ b/contracts/hackatom/src/contract.rs @@ -51,6 +51,9 @@ pub enum HandleMsg { AllocateLargeMemory {}, /// Trigger a panic to ensure framework handles gracefully Panic {}, + /// Starting with CosmWasm 0.10, some API calls return user errors back to the contract. + /// This triggers such user errors, ensuring the transaction does not fail in the backend. + UserErrorsInApiCalls {}, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -134,6 +137,7 @@ pub fn handle( HandleMsg::MemoryLoop {} => do_memory_loop(), HandleMsg::AllocateLargeMemory {} => do_allocate_large_memory(), HandleMsg::Panic {} => do_panic(), + HandleMsg::UserErrorsInApiCalls {} => do_user_errors_in_api_calls(&deps.api), } } @@ -219,6 +223,44 @@ fn do_panic() -> StdResult { panic!("This page intentionally faulted"); } +fn do_user_errors_in_api_calls(api: &A) -> StdResult { + // Canonicalize + + let empty = HumanAddr::from(""); + match api.canonical_address(&empty).unwrap_err() { + StdError::GenericErr { .. } => {} + err => panic!("Unexpected error: {:?}", err), + } + + let invalid_bech32 = HumanAddr::from("bn93hg934hg08q340g8u4jcau3"); + match api.canonical_address(&invalid_bech32).unwrap_err() { + StdError::GenericErr { .. } => {} + err => panic!("Unexpected error: {:?}", err), + } + + // Humanize + + let empty: CanonicalAddr = vec![].into(); + match api.human_address(&empty).unwrap_err() { + StdError::GenericErr { .. } => {} + err => panic!("Unexpected error: {:?}", err), + } + + let too_short: CanonicalAddr = vec![0xAA, 0xBB, 0xCC].into(); + match api.human_address(&too_short).unwrap_err() { + StdError::GenericErr { .. } => {} + err => panic!("Unexpected error: {:?}", err), + } + + let wrong_length: CanonicalAddr = vec![0xA6; 17].into(); + match api.human_address(&wrong_length).unwrap_err() { + StdError::GenericErr { .. } => {} + err => panic!("Unexpected error: {:?}", err), + } + + Ok(HandleResponse::default()) +} + pub fn query( deps: &Extern, msg: QueryMsg, @@ -502,6 +544,22 @@ mod tests { let _ = handle(&mut deps, handle_env, HandleMsg::Panic {}); } + #[test] + fn handle_user_errors_in_api_calls() { + let mut deps = mock_dependencies(20, &[]); + + let init_msg = InitMsg { + verifier: HumanAddr::from("verifies"), + beneficiary: HumanAddr::from("benefits"), + }; + let init_env = mock_env("creator", &coins(1000, "earth")); + let init_res = init(&mut deps, init_env, init_msg).unwrap(); + assert_eq!(0, init_res.messages.len()); + + let handle_env = mock_env("anyone", &[]); + handle(&mut deps, handle_env, HandleMsg::UserErrorsInApiCalls {}).unwrap(); + } + #[test] fn query_recursive() { // the test framework doesn't handle contracts querying contracts yet, diff --git a/contracts/hackatom/tests/integration.rs b/contracts/hackatom/tests/integration.rs index 8ad6fc332a..c3a8574840 100644 --- a/contracts/hackatom/tests/integration.rs +++ b/contracts/hackatom/tests/integration.rs @@ -34,6 +34,19 @@ use hackatom::contract::{HandleMsg, InitMsg, MigrateMsg, QueryMsg, State, CONFIG static WASM: &[u8] = include_bytes!("../target/wasm32-unknown-unknown/release/hackatom.wasm"); +fn make_init_msg() -> (InitMsg, HumanAddr) { + let verifier = HumanAddr::from("verifies"); + let beneficiary = HumanAddr::from("benefits"); + let creator = HumanAddr::from("creator"); + ( + InitMsg { + verifier: verifier.clone(), + beneficiary: beneficiary.clone(), + }, + creator, + ) +} + #[test] fn proper_initialization() { let mut deps = mock_instance(WASM, &[]); @@ -270,6 +283,19 @@ fn handle_release_fails_for_wrong_sender() { ); } +#[test] +fn handle_user_errors_in_api_calls() { + let mut deps = mock_instance(WASM, &[]); + + let (init_msg, creator) = make_init_msg(); + let init_env = mock_env(creator.as_str(), &[]); + let _init_res: InitResponse = init(&mut deps, init_env, init_msg).unwrap(); + + let handle_env = mock_env(creator.as_str(), &[]); + let _handle_res: HandleResponse = + handle(&mut deps, handle_env, HandleMsg::UserErrorsInApiCalls {}).unwrap(); +} + #[test] fn passes_io_tests() { let mut deps = mock_instance(WASM, &[]); @@ -283,19 +309,6 @@ mod singlepass_tests { use cosmwasm_std::{to_vec, Empty}; use cosmwasm_vm::call_handle; - fn make_init_msg() -> (InitMsg, HumanAddr) { - let verifier = HumanAddr::from("verifies"); - let beneficiary = HumanAddr::from("benefits"); - let creator = HumanAddr::from("creator"); - ( - InitMsg { - verifier: verifier.clone(), - beneficiary: beneficiary.clone(), - }, - creator, - ) - } - #[test] fn handle_panic() { let mut deps = mock_instance(WASM, &[]); From 5bcfcf3e356f98ee44250f07f3f5f136e693e7cb Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 30 Jul 2020 11:41:34 +0200 Subject: [PATCH 4/6] Run handle_panic independent of singlepass and test error type --- contracts/hackatom/tests/integration.rs | 54 ++++++++++++------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/contracts/hackatom/tests/integration.rs b/contracts/hackatom/tests/integration.rs index c3a8574840..9fc548c758 100644 --- a/contracts/hackatom/tests/integration.rs +++ b/contracts/hackatom/tests/integration.rs @@ -18,16 +18,16 @@ //! 4. Anywhere you see query(&deps, ...) you must replace it with query(&mut deps, ...) use cosmwasm_std::{ - coins, from_binary, log, AllBalanceResponse, BankMsg, HandleResponse, HandleResult, HumanAddr, - InitResponse, InitResult, MigrateResponse, StdError, + coins, from_binary, log, to_vec, AllBalanceResponse, BankMsg, Empty, HandleResponse, + HandleResult, HumanAddr, InitResponse, InitResult, MigrateResponse, StdError, }; use cosmwasm_vm::{ - from_slice, + call_handle, from_slice, testing::{ handle, init, migrate, mock_env, mock_instance, mock_instance_with_balances, query, test_io, MOCK_CONTRACT_ADDR, }, - Api, Storage, + Api, Storage, VmError, }; use hackatom::contract::{HandleMsg, InitMsg, MigrateMsg, QueryMsg, State, CONFIG_KEY}; @@ -283,6 +283,29 @@ fn handle_release_fails_for_wrong_sender() { ); } +#[test] +fn handle_panic() { + let mut deps = mock_instance(WASM, &[]); + + let (init_msg, creator) = make_init_msg(); + let init_env = mock_env(creator.as_str(), &[]); + let init_res: InitResponse = init(&mut deps, init_env, init_msg).unwrap(); + assert_eq!(0, init_res.messages.len()); + + let handle_env = mock_env(creator.as_str(), &[]); + // panic inside contract should not panic out here + // Note: we need to use the production-call, not the testing call (which unwraps any vm error) + let handle_res = call_handle::<_, _, _, Empty>( + &mut deps, + &handle_env, + &to_vec(&HandleMsg::Panic {}).unwrap(), + ); + match handle_res.unwrap_err() { + VmError::RuntimeErr { .. } => {} + err => panic!("Unexpected error: {:?}", err), + } +} + #[test] fn handle_user_errors_in_api_calls() { let mut deps = mock_instance(WASM, &[]); @@ -306,29 +329,6 @@ fn passes_io_tests() { mod singlepass_tests { use super::*; - use cosmwasm_std::{to_vec, Empty}; - use cosmwasm_vm::call_handle; - - #[test] - fn handle_panic() { - let mut deps = mock_instance(WASM, &[]); - - let (init_msg, creator) = make_init_msg(); - let init_env = mock_env(creator.as_str(), &[]); - let init_res: InitResponse = init(&mut deps, init_env, init_msg).unwrap(); - assert_eq!(0, init_res.messages.len()); - - let handle_env = mock_env(creator.as_str(), &[]); - // panic inside contract should not panic out here - // Note: we need to use the production-call, not the testing call (which unwraps any vm error) - let handle_res = call_handle::<_, _, _, Empty>( - &mut deps, - &handle_env, - &to_vec(&HandleMsg::Panic {}).unwrap(), - ); - assert!(handle_res.is_err()); - } - #[test] fn handle_cpu_loop() { let mut deps = mock_instance(WASM, &[]); From 4335c975655b9422bcc4b384a7c13d596f303e37 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 30 Jul 2020 11:45:01 +0200 Subject: [PATCH 5/6] Convert panics to errors for better debugging --- contracts/hackatom/src/contract.rs | 35 +++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/contracts/hackatom/src/contract.rs b/contracts/hackatom/src/contract.rs index e093369d80..0e7328056e 100644 --- a/contracts/hackatom/src/contract.rs +++ b/contracts/hackatom/src/contract.rs @@ -229,13 +229,23 @@ fn do_user_errors_in_api_calls(api: &A) -> StdResult { let empty = HumanAddr::from(""); match api.canonical_address(&empty).unwrap_err() { StdError::GenericErr { .. } => {} - err => panic!("Unexpected error: {:?}", err), + err => { + return Err(StdError::generic_err(format!( + "Unexpected error in do_user_errors_in_api_calls: {:?}", + err + ))) + } } let invalid_bech32 = HumanAddr::from("bn93hg934hg08q340g8u4jcau3"); match api.canonical_address(&invalid_bech32).unwrap_err() { StdError::GenericErr { .. } => {} - err => panic!("Unexpected error: {:?}", err), + err => { + return Err(StdError::generic_err(format!( + "Unexpected error in do_user_errors_in_api_calls: {:?}", + err + ))) + } } // Humanize @@ -243,19 +253,34 @@ fn do_user_errors_in_api_calls(api: &A) -> StdResult { let empty: CanonicalAddr = vec![].into(); match api.human_address(&empty).unwrap_err() { StdError::GenericErr { .. } => {} - err => panic!("Unexpected error: {:?}", err), + err => { + return Err(StdError::generic_err(format!( + "Unexpected error in do_user_errors_in_api_calls: {:?}", + err + ))) + } } let too_short: CanonicalAddr = vec![0xAA, 0xBB, 0xCC].into(); match api.human_address(&too_short).unwrap_err() { StdError::GenericErr { .. } => {} - err => panic!("Unexpected error: {:?}", err), + err => { + return Err(StdError::generic_err(format!( + "Unexpected error in do_user_errors_in_api_calls: {:?}", + err + ))) + } } let wrong_length: CanonicalAddr = vec![0xA6; 17].into(); match api.human_address(&wrong_length).unwrap_err() { StdError::GenericErr { .. } => {} - err => panic!("Unexpected error: {:?}", err), + err => { + return Err(StdError::generic_err(format!( + "Unexpected error in do_user_errors_in_api_calls: {:?}", + err + ))) + } } Ok(HandleResponse::default()) From e9958b4601357406ebd8dc40ff8298103f22696b Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 30 Jul 2020 12:08:40 +0200 Subject: [PATCH 6/6] Accept GasDepletion in panic test --- contracts/hackatom/tests/integration.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/hackatom/tests/integration.rs b/contracts/hackatom/tests/integration.rs index 9fc548c758..9a15e7a814 100644 --- a/contracts/hackatom/tests/integration.rs +++ b/contracts/hackatom/tests/integration.rs @@ -301,7 +301,8 @@ fn handle_panic() { &to_vec(&HandleMsg::Panic {}).unwrap(), ); match handle_res.unwrap_err() { - VmError::RuntimeErr { .. } => {} + // TODO: Don't accept GasDepletion here (https://github.com/CosmWasm/cosmwasm/issues/501) + VmError::RuntimeErr { .. } | VmError::GasDepletion => {} err => panic!("Unexpected error: {:?}", err), } }