diff --git a/contracts/dynamic-callee-contract/src/contract.rs b/contracts/dynamic-callee-contract/src/contract.rs index bbc982b74..328f2df31 100644 --- a/contracts/dynamic-callee-contract/src/contract.rs +++ b/contracts/dynamic-callee-contract/src/contract.rs @@ -53,6 +53,11 @@ fn pong_env() -> Env { GlobalApi::env() } +#[callable_point] +fn do_panic() { + panic!(); +} + #[derive(Contract)] struct Me { address: Addr, diff --git a/contracts/dynamic-callee-contract/tests/integration.rs b/contracts/dynamic-callee-contract/tests/integration.rs index 144ef2a67..8e9bbd3cf 100644 --- a/contracts/dynamic-callee-contract/tests/integration.rs +++ b/contracts/dynamic-callee-contract/tests/integration.rs @@ -3,7 +3,7 @@ use cosmwasm_vm::testing::{ mock_backend, mock_env, read_data_from_mock_env, write_data_to_mock_env, Contract, MockApi, MockInstanceOptions, MockQuerier, MockStorage, MOCK_CONTRACT_ADDR, }; -use cosmwasm_vm::Instance; +use cosmwasm_vm::{Instance, VmError}; use dynamic_callee_contract::contract::ExampleStruct; use std::collections::HashMap; use wasmer_types::{FunctionType, Type}; @@ -27,6 +27,7 @@ fn required_exports() -> Vec<(String, FunctionType)> { ([Type::I32, Type::I32], [Type::I32]).into(), ), (String::from("pong_env"), ([], [Type::I32]).into()), + (String::from("do_panic"), ([], []).into()), ] } @@ -207,3 +208,26 @@ fn callable_point_pong_env_works() { let result: Env = from_slice(&serialized_return).unwrap(); assert_eq!(result.contract.address, Addr::unchecked(MOCK_CONTRACT_ADDR)); } + +#[test] +fn callable_point_do_panic_raises_runtime_error() { + let instance = make_callee_instance(); + + let required_exports = required_exports(); + instance + .env + .set_serialized_env(&to_vec(&mock_env()).unwrap()); + let export_index = 5; + assert_eq!("do_panic".to_string(), required_exports[export_index].0); + let call_result = + instance.call_function_strict(&required_exports[export_index].1, "do_panic", &[]); + + match call_result.unwrap_err() { + VmError::RuntimeErr { msg, .. } => { + // Because content in the latter part depends on the environment, + // comparing whether the error begins with panic error or not. + assert!(msg.starts_with("Wasmer runtime error: RuntimeError: unreachable")) + } + e => panic!("Unexpected error: {:?}", e), + } +} diff --git a/contracts/dynamic-caller-contract/schema/execute_msg.json b/contracts/dynamic-caller-contract/schema/execute_msg.json index 50b3af4d3..c1fe958b4 100644 --- a/contracts/dynamic-caller-contract/schema/execute_msg.json +++ b/contracts/dynamic-caller-contract/schema/execute_msg.json @@ -33,6 +33,18 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "do_panic" + ], + "properties": { + "do_panic": { + "type": "object" + } + }, + "additionalProperties": false } ], "definitions": { diff --git a/contracts/dynamic-caller-contract/src/contract.rs b/contracts/dynamic-caller-contract/src/contract.rs index e4bab16ec..077863231 100644 --- a/contracts/dynamic-caller-contract/src/contract.rs +++ b/contracts/dynamic-caller-contract/src/contract.rs @@ -32,6 +32,7 @@ trait Callee: Contract { fn pong_with_tuple_takes_2_args(&self, input1: String, input2: i32) -> (String, i32); fn pong_env(&self) -> Env; fn reentrancy(&self, addr: Addr); + fn do_panic(&self); } #[cfg(not(target_arch = "wasm32"))] @@ -62,6 +63,10 @@ impl Callee for CalleeContract { fn reentrancy(&self, _addr: Addr) { panic!() } + + fn do_panic(&self) { + panic!() + } } // Note, you can use StdResult in some functions where you do not @@ -90,6 +95,7 @@ pub fn execute( match msg { ExecuteMsg::Ping { ping_num } => try_ping(deps, ping_num), ExecuteMsg::TryReEntrancy {} => try_re_entrancy(deps, env), + ExecuteMsg::DoPanic {} => try_do_panic(deps, env), } } @@ -131,6 +137,13 @@ pub fn try_re_entrancy(deps: DepsMut, env: Env) -> Result Result { + let address = from_slice(&deps.storage.get(b"dynamic_callee_contract").unwrap())?; + let contract = CalleeContract { address }; + contract.do_panic(); + Ok(Response::default()) +} + #[callable_point] fn should_never_be_called() {} diff --git a/contracts/dynamic-caller-contract/src/msg.rs b/contracts/dynamic-caller-contract/src/msg.rs index 251ba7918..53c702e6b 100644 --- a/contracts/dynamic-caller-contract/src/msg.rs +++ b/contracts/dynamic-caller-contract/src/msg.rs @@ -12,6 +12,7 @@ pub struct InstantiateMsg { pub enum ExecuteMsg { Ping { ping_num: Uint128 }, TryReEntrancy {}, + DoPanic {}, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] diff --git a/contracts/dynamic-caller-contract/tests/integration.rs b/contracts/dynamic-caller-contract/tests/integration.rs index 562139678..7c227d771 100644 --- a/contracts/dynamic-caller-contract/tests/integration.rs +++ b/contracts/dynamic-caller-contract/tests/integration.rs @@ -32,6 +32,11 @@ fn required_imports() -> Vec<(String, String, FunctionType)> { String::from("CalleeContract"), ([Type::I32], [Type::I32]).into(), ), + ( + String::from("do_panic"), + String::from("CalleeContract"), + ([Type::I32], []).into(), + ), ] }