diff --git a/crates/e2e/src/client.rs b/crates/e2e/src/client.rs index 3f9981d2cc5..4860bbf75cb 100644 --- a/crates/e2e/src/client.rs +++ b/crates/e2e/src/client.rs @@ -33,6 +33,7 @@ use super::{ }; use contract_metadata::ContractMetadata; use ink_env::Environment; +use ink_primitives::MessageResult; use sp_runtime::traits::{ IdentifyAccount, @@ -124,7 +125,7 @@ pub struct CallResult { pub events: ExtrinsicEvents, /// Contains the result of decoding the return value of the called /// function. - pub value: Result, + pub value: Result, scale::Error>, /// Returns the bytes of the encoded dry-run return value. pub data: Vec, } @@ -139,12 +140,19 @@ where /// Panics if the value could not be decoded. The raw bytes can be accessed /// via [`return_data`]. pub fn return_value(self) -> V { - self.value.unwrap_or_else(|err| { - panic!( - "decoding dry run result to ink! message return type failed: {}", - err - ) - }) + self.value + .unwrap_or_else(|env_err| { + panic!( + "Decoding dry run result to ink! message return type failed: {}", + env_err + ) + }) + .unwrap_or_else(|lang_err| { + panic!( + "Encountered a `LangError` while decoding dry run result to ink! message: {:?}", + lang_err + ) + }) } /// Returns true if the specified event was triggered by the call. @@ -655,7 +663,7 @@ where } let bytes = &dry_run.result.as_ref().unwrap().data; - let value: Result = + let value: Result, scale::Error> = scale::Decode::decode(&mut bytes.as_ref()); Ok(CallResult { diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index e4821480a67..0683fcf4b09 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -268,7 +268,9 @@ where /// - If the called contract execution has trapped. /// - If the called contract ran out of gas upon execution. /// - If the returned value failed to decode properly. -pub fn invoke_contract(params: &CallParams, Args, R>) -> Result +pub fn invoke_contract( + params: &CallParams, Args, R>, +) -> Result> where E: Environment, Args: scale::Encode, diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index dc3a8832b0e..39beb23cdee 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -414,7 +414,7 @@ pub trait TypedEnvBackend: EnvBackend { fn invoke_contract( &mut self, call_data: &CallParams, Args, R>, - ) -> Result + ) -> Result> where E: Environment, Args: scale::Encode, diff --git a/crates/env/src/call/call_builder.rs b/crates/env/src/call/call_builder.rs index 9a45106ca7d..3c208c5cddb 100644 --- a/crates/env/src/call/call_builder.rs +++ b/crates/env/src/call/call_builder.rs @@ -109,7 +109,27 @@ where /// Invokes the contract with the given built-up call parameters. /// /// Returns the result of the contract execution. + /// + /// # Panics + /// + /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle + /// those use the [`try_invoke`][`CallParams::try_invoke`] method instead. pub fn invoke(&self) -> Result { + crate::invoke_contract(self).map(|inner| { + inner.unwrap_or_else(|lang_error| { + panic!("Cross-contract call failed with {:?}", lang_error) + }) + }) + } + + /// Invokes the contract with the given built-up call parameters. + /// + /// Returns the result of the contract execution. + /// + /// # Note + /// + /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. + pub fn try_invoke(&self) -> Result, crate::Error> { crate::invoke_contract(self) } } @@ -173,7 +193,7 @@ where /// ) /// .returns::<()>() /// .fire() -/// .unwrap(); +/// .expect("Got an error from the Contract's pallet."); /// ``` /// /// ## Example 2: With Return Value @@ -209,7 +229,7 @@ where /// ) /// .returns::() /// .fire() -/// .unwrap(); +/// .expect("Got an error from the Contract's pallet."); /// ``` /// /// ## Example 3: Delegate call @@ -237,7 +257,47 @@ where /// ) /// .returns::() /// .fire() -/// .unwrap(); +/// .expect("Got an error from the Contract's pallet."); +/// ``` +/// +/// # Handling `LangError`s +/// +/// It is also important to note that there are certain types of errors which can happen during +/// cross-contract calls which can be handled know as [`LangError`][`ink_primitives::LangError`]. +/// +/// If you want to handle these errors use the [`CallBuilder::try_fire`] methods instead of the +/// [`CallBuilder::fire`] ones. +/// +/// **Note:** The shown examples panic because there is currently no cross-calling +/// support in the off-chain testing environment. However, this code +/// should work fine in on-chain environments. +/// +/// ## Example: Handling a `LangError` +/// +/// ```should_panic +/// # use ::ink_env::{ +/// # Environment, +/// # DefaultEnvironment, +/// # call::{build_call, Selector, ExecutionInput} +/// # }; +/// # use ink_env::call::Call; +/// # type AccountId = ::AccountId; +/// # type Balance = ::Balance; +/// let call_result = build_call::() +/// .call_type( +/// Call::new() +/// .callee(AccountId::from([0x42; 32])) +/// .gas_limit(5000) +/// .transferred_value(10), +/// ) +/// .try_fire() +/// .expect("Got an error from the Contract's pallet."); +/// +/// match call_result { +/// Ok(_) => unimplemented!(), +/// Err(e @ ink_primitives::LangError::CouldNotReadInput) => unimplemented!(), +/// Err(_) => unimplemented!(), +/// } /// ``` #[allow(clippy::type_complexity)] pub fn build_call() -> CallBuilder< @@ -597,9 +657,23 @@ where E: Environment, { /// Invokes the cross-chain function call. + /// + /// # Panics + /// + /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle + /// those use the [`try_fire`][`CallBuilder::try_fire`] method instead. pub fn fire(self) -> Result<(), Error> { self.params().invoke() } + + /// Invokes the cross-chain function call. + /// + /// # Note + /// + /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. + pub fn try_fire(self) -> Result, Error> { + self.params().try_invoke() + } } impl @@ -626,9 +700,23 @@ where R: scale::Decode, { /// Invokes the cross-chain function call and returns the result. + /// + /// # Panics + /// + /// This method panics if it encounters an [`ink_primitives::LangError`]. If you want to handle + /// those use the [`try_fire`][`CallBuilder::try_fire`] method instead. pub fn fire(self) -> Result { self.params().invoke() } + + /// Invokes the cross-chain function call and returns the result. + /// + /// # Note + /// + /// On failure this returns an [`ink_primitives::LangError`] which can be handled by the caller. + pub fn try_fire(self) -> Result, Error> { + self.params().try_invoke() + } } impl diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index e94c36568d4..a17bdc3a5ff 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -440,7 +440,7 @@ impl TypedEnvBackend for EnvInstance { fn invoke_contract( &mut self, params: &CallParams, Args, R>, - ) -> Result + ) -> Result> where E: Environment, Args: scale::Encode, diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index d140fc9949c..6f3b7572c04 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -415,7 +415,7 @@ impl TypedEnvBackend for EnvInstance { fn invoke_contract( &mut self, params: &CallParams, Args, R>, - ) -> Result + ) -> Result> where E: Environment, Args: scale::Encode, diff --git a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs index 9d3232133f8..e85e52b0ee3 100644 --- a/crates/ink/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/ink/codegen/src/generator/as_dependency/call_builder.rs @@ -369,7 +369,10 @@ impl CallBuilder<'_> { let input_types = generator::input_types(message.inputs()); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let mut_tok = callable.receiver().is_ref_mut().then(|| quote! { mut }); - let return_type = message.wrapped_output(); + let return_type = message + .output() + .map(quote::ToTokens::to_token_stream) + .unwrap_or_else(|| quote::quote! { () }); let output_span = return_type.span(); let output_type = quote_spanned!(output_span=> ::ink::env::call::CallBuilder< diff --git a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs index 588d14fd8af..2cf5fe71b26 100644 --- a/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/ink/codegen/src/generator/as_dependency/contract_ref.rs @@ -370,7 +370,7 @@ impl ContractRef<'_> { ) -> #wrapped_output_type { ::#call_operator(self) .#message_ident( #( #input_bindings ),* ) - .fire() + .try_fire() .unwrap_or_else(|error| ::core::panic!( "encountered error while calling {}::{}: {:?}", ::core::stringify!(#storage_ident), diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index c9fe7491919..cd691cfb875 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -519,7 +519,10 @@ where /// ) /// .returns::() /// .params(); - /// self.env().invoke_contract(&call_params).unwrap_or_else(|err| panic!("call invocation must succeed: {:?}", err)) + /// + /// self.env().invoke_contract(&call_params) + /// .unwrap_or_else(|env_err| panic!("Received an error from the Environment: {:?}", env_err)) + /// .unwrap_or_else(|lang_err| panic!("Received a `LangError`: {:?}", lang_err)) /// } /// # /// # } @@ -532,7 +535,7 @@ where pub fn invoke_contract( self, params: &CallParams, Args, R>, - ) -> Result + ) -> Result> where Args: scale::Encode, R: scale::Decode, diff --git a/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr index e6c2260060a..a083a628f30 100644 --- a/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr +++ b/crates/ink/tests/ui/contract/fail/message-input-non-codec.stderr @@ -53,11 +53,11 @@ note: required by a bound in `ExecutionInput::>::push_arg` -error[E0599]: the method `fire` exists for struct `ink::ink_env::call::CallBuilder>, Set, ArgumentList>>>, Set>>>`, but its trait bounds were not satisfied +error[E0599]: the method `try_fire` exists for struct `ink::ink_env::call::CallBuilder>, Set, ArgumentList>>>, Set>>`, but its trait bounds were not satisfied --> tests/ui/contract/fail/message-input-non-codec.rs:16:9 | 16 | pub fn message(&self, _input: NonCodecType) {} - | ^^^ method cannot be called on `ink::ink_env::call::CallBuilder>, Set, ArgumentList>>>, Set>>>` due to unsatisfied trait bounds + | ^^^ method cannot be called on `ink::ink_env::call::CallBuilder>, Set, ArgumentList>>>, Set>>` due to unsatisfied trait bounds | ::: $WORKSPACE/crates/env/src/call/execution_input.rs | diff --git a/crates/ink/tests/ui/contract/fail/message-returns-non-codec.stderr b/crates/ink/tests/ui/contract/fail/message-returns-non-codec.stderr index b5565368175..1bdb9e94006 100644 --- a/crates/ink/tests/ui/contract/fail/message-returns-non-codec.stderr +++ b/crates/ink/tests/ui/contract/fail/message-returns-non-codec.stderr @@ -34,16 +34,19 @@ note: required by a bound in `return_value` | R: scale::Encode, | ^^^^^^^^^^^^^ required by this bound in `return_value` -error[E0599]: the method `fire` exists for struct `ink::ink_env::call::CallBuilder>, Set>>, Set>>>`, but its trait bounds were not satisfied +error[E0599]: the method `try_fire` exists for struct `ink::ink_env::call::CallBuilder>, Set>>, Set>>`, but its trait bounds were not satisfied --> tests/ui/contract/fail/message-returns-non-codec.rs:16:9 | +4 | pub struct NonCodecType; + | ----------------------- doesn't satisfy `NonCodecType: parity_scale_codec::Decode` +... 16 | pub fn message(&self) -> NonCodecType { - | ^^^ method cannot be called on `ink::ink_env::call::CallBuilder>, Set>>, Set>>>` due to unsatisfied trait bounds - | - ::: $RUST/core/src/result.rs - | - | pub enum Result { - | --------------------- doesn't satisfy `_: parity_scale_codec::Decode` + | ^^^ method cannot be called on `ink::ink_env::call::CallBuilder>, Set>>, Set>>` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: - `Result: parity_scale_codec::Decode` + `NonCodecType: parity_scale_codec::Decode` +note: the following trait must be implemented + --> $CARGO/parity-scale-codec-3.2.2/src/codec.rs + | + | pub trait Decode: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/ink/tests/ui/trait_def/fail/message_output_non_codec.stderr b/crates/ink/tests/ui/trait_def/fail/message_output_non_codec.stderr index d9b358b613f..2c487dcca6f 100644 --- a/crates/ink/tests/ui/trait_def/fail/message_output_non_codec.stderr +++ b/crates/ink/tests/ui/trait_def/fail/message_output_non_codec.stderr @@ -1,39 +1,39 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied - --> tests/ui/trait_def/fail/message_output_non_codec.rs:6:26 - | -6 | fn message(&self) -> NonCodec; - | ^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` - | - = help: the following other types implement trait `WrapperTypeEncode`: - &T - &mut T - Arc - Box - Cow<'a, T> - Rc - String - Vec - parity_scale_codec::Ref<'a, T, U> - = note: required for `NonCodec` to implement `Encode` + --> tests/ui/trait_def/fail/message_output_non_codec.rs:6:26 + | +6 | fn message(&self) -> NonCodec; + | ^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` + | + = help: the following other types implement trait `WrapperTypeEncode`: + &T + &mut T + Arc + Box + Cow<'a, T> + Rc + String + Vec + parity_scale_codec::Ref<'a, T, U> + = note: required for `NonCodec` to implement `Encode` note: required by a bound in `DispatchOutput` - --> src/codegen/dispatch/type_check.rs - | - | T: scale::Encode + 'static; - | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` + --> src/codegen/dispatch/type_check.rs + | + | T: scale::Encode + 'static; + | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` error[E0599]: the method `fire` exists for struct `CallBuilder>, Set>>, Set>>`, but its trait bounds were not satisfied - --> tests/ui/trait_def/fail/message_output_non_codec.rs:5:5 - | -1 | pub struct NonCodec; - | ------------------- doesn't satisfy `NonCodec: parity_scale_codec::Decode` + --> tests/ui/trait_def/fail/message_output_non_codec.rs:5:5 + | +1 | pub struct NonCodec; + | ------------------- doesn't satisfy `NonCodec: parity_scale_codec::Decode` ... -5 | #[ink(message)] - | ^ method cannot be called on `CallBuilder>, Set>>, Set>>` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `NonCodec: parity_scale_codec::Decode` +5 | #[ink(message)] + | ^ method cannot be called on `CallBuilder>, Set>>, Set>>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NonCodec: parity_scale_codec::Decode` note: the following trait must be implemented - --> $CARGO/parity-scale-codec-3.2.1/src/codec.rs - | - | pub trait Decode: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^ + --> $CARGO/parity-scale-codec-3.2.2/src/codec.rs + | + | pub trait Decode: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/examples/delegator/lib.rs b/examples/delegator/lib.rs index ec45e70c0d3..074ac5cae7b 100644 --- a/examples/delegator/lib.rs +++ b/examples/delegator/lib.rs @@ -174,8 +174,7 @@ mod delegator { .call(&ink_e2e::bob(), get, 0, None) .await .expect("calling `get` failed") - .return_value() - .expect("calling `get` returned a `LangError`"); + .return_value(); assert_eq!(value, 1234); let change = build_message::(delegator_acc_id.clone()) .call(|contract| contract.change(6)); @@ -191,8 +190,7 @@ mod delegator { .call(&ink_e2e::bob(), get, 0, None) .await .expect("calling `get` failed") - .return_value() - .expect("calling `get` returned a `LangError`"); + .return_value(); assert_eq!(value, 1234 + 6); // when @@ -216,8 +214,7 @@ mod delegator { .call(&ink_e2e::bob(), get, 0, None) .await .expect("calling `get` failed") - .return_value() - .expect("calling `get` returned a `LangError`"); + .return_value(); assert_eq!(value, 1234 + 6 - 3); Ok(()) diff --git a/examples/erc1155/lib.rs b/examples/erc1155/lib.rs index 9140fa21f80..55f86b16f5a 100644 --- a/examples/erc1155/lib.rs +++ b/examples/erc1155/lib.rs @@ -365,7 +365,7 @@ mod erc1155 { // If our recipient is a smart contract we need to see if they accept or // reject this transfer. If they reject it we need to revert the call. - let params = build_call::() + let result = build_call::() .call_type(Call::new().callee(to).gas_limit(5000)) .exec_input( ExecutionInput::new(Selector::new(ON_ERC_1155_RECEIVED_SELECTOR)) @@ -376,9 +376,10 @@ mod erc1155 { .push_arg(data), ) .returns::>() - .params(); + .params() + .invoke(); - match ink::env::invoke_contract(¶ms) { + match result { Ok(v) => { ink::env::debug_println!( "Received return value \"{:?}\" from contract {:?}", diff --git a/examples/erc20/lib.rs b/examples/erc20/lib.rs index 4608550f0aa..65e14a15f29 100644 --- a/examples/erc20/lib.rs +++ b/examples/erc20/lib.rs @@ -577,14 +577,10 @@ mod erc20 { // then assert_eq!( total_supply, - total_supply_res.return_value().unwrap(), + total_supply_res.return_value(), "total_supply" ); - assert_eq!( - transfer_to_bob, - balance_of_res.return_value().unwrap(), - "balance_of" - ); + assert_eq!(transfer_to_bob, balance_of_res.return_value(), "balance_of"); Ok(()) } @@ -671,7 +667,7 @@ mod erc20 { assert_eq!( total_supply - approved_value, - balance_of_res.return_value().unwrap(), + balance_of_res.return_value(), "balance_of" ); diff --git a/examples/flipper/lib.rs b/examples/flipper/lib.rs index d4d0c82b2ac..3525b8b633d 100644 --- a/examples/flipper/lib.rs +++ b/examples/flipper/lib.rs @@ -75,7 +75,7 @@ pub mod flipper { .call(&ink_e2e::bob(), get, 0, None) .await .expect("get failed"); - assert!(matches!(get_res.return_value(), Ok(false))); + assert!(matches!(get_res.return_value(), false)); // when let flip = build_message::(contract_acc_id.clone()) @@ -92,7 +92,7 @@ pub mod flipper { .call(&ink_e2e::bob(), get, 0, None) .await .expect("get failed"); - assert!(matches!(get_res.return_value(), Ok(true))); + assert!(matches!(get_res.return_value(), true)); Ok(()) } @@ -116,7 +116,7 @@ pub mod flipper { .call(&ink_e2e::bob(), get, 0, None) .await .expect("get failed"); - assert!(matches!(get_res.return_value(), Ok(false))); + assert!(matches!(get_res.return_value(), false)); Ok(()) } diff --git a/examples/lang-err-integration-tests/call-builder/lib.rs b/examples/lang-err-integration-tests/call-builder/lib.rs index 5459e33548a..0a3de1e94ef 100755 --- a/examples/lang-err-integration-tests/call-builder/lib.rs +++ b/examples/lang-err-integration-tests/call-builder/lib.rs @@ -43,8 +43,8 @@ mod call_builder { let result = build_call::() .call_type(Call::new().callee(address)) .exec_input(ExecutionInput::new(Selector::new(selector))) - .returns::>() - .fire() + .returns::<()>() + .try_fire() .expect("Error from the Contracts pallet."); match result { @@ -56,6 +56,25 @@ mod call_builder { } } + /// Call a contract using the `CallBuilder`. + /// + /// Since we can't use the `CallBuilder` in a test environment directly we need this + /// wrapper to test things like crafting calls with invalid selectors. + /// + /// This message does not allow the caller to handle any `LangErrors`, for that use the + /// `call` message instead. + #[ink(message)] + pub fn fire(&mut self, address: AccountId, selector: [u8; 4]) { + use ink::env::call::build_call; + + build_call::() + .call_type(Call::new().callee(address)) + .exec_input(ExecutionInput::new(Selector::new(selector))) + .returns::<()>() + .fire() + .expect("Error from the Contracts pallet.") + } + #[ink(message)] pub fn call_instantiate( &mut self, @@ -79,6 +98,8 @@ mod call_builder { // NOTE: Right now we can't handle any `LangError` from `instantiate`, we can only tell // that our contract reverted (i.e we see error from the Contracts pallet). + // + // This will be fixed with #1512. result.ok().map(|id| ink::ToAccountId::to_account_id(&id)) } } @@ -123,9 +144,7 @@ mod call_builder { .call(&ink_e2e::charlie(), flipper_get, 0, None) .await .expect("Calling `flipper::get` failed"); - let initial_value = get_call_result - .return_value() - .expect("Input is valid, call must not fail."); + let initial_value = get_call_result.return_value(); let invalid_selector = [0x00, 0x00, 0x00, 0x00]; let call = build_message::(contract_acc_id) @@ -135,9 +154,7 @@ mod call_builder { .await .expect("Calling `call_builder::call` failed"); - let flipper_result = call_result - .return_value() - .expect("Call to `call_builder::call` failed"); + let flipper_result = call_result.return_value(); assert!(matches!( flipper_result, @@ -150,14 +167,56 @@ mod call_builder { .call(&ink_e2e::charlie(), flipper_get, 0, None) .await .expect("Calling `flipper::get` failed"); - let flipped_value = get_call_result - .return_value() - .expect("Input is valid, call must not fail."); + let flipped_value = get_call_result.return_value(); assert!(flipped_value == initial_value); Ok(()) } + #[ink_e2e::test(additional_contracts = "../integration-flipper/Cargo.toml")] + async fn e2e_invalid_message_selector_panics_on_fire( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let constructor = CallBuilderTestRef::new(); + let contract_acc_id = client + .instantiate("call_builder", &ink_e2e::ferdie(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + let flipper_constructor = FlipperRef::new_default(); + let flipper_acc_id = client + .instantiate( + "integration_flipper", + &ink_e2e::ferdie(), + flipper_constructor, + 0, + None, + ) + .await + .expect("instantiate `flipper` failed") + .account_id; + + // Since `LangError`s can't be handled by the `CallBuilder::fire()` method we expect + // this to panic. + let invalid_selector = [0x00, 0x00, 0x00, 0x00]; + let call = build_message::(contract_acc_id) + .call(|contract| contract.fire(flipper_acc_id, invalid_selector)); + let call_result = client.call(&ink_e2e::ferdie(), call, 0, None).await; + + assert!(call_result.is_err()); + let contains_err_msg = match call_result.unwrap_err() { + ink_e2e::Error::CallDryRun(dry_run) => { + String::from_utf8_lossy(&dry_run.debug_message) + .contains("Cross-contract call failed with CouldNotReadInput") + } + _ => false, + }; + assert!(contains_err_msg); + + Ok(()) + } + #[ink_e2e::test(additional_contracts = "../constructors-return-value/Cargo.toml")] async fn e2e_create_builder_works_with_valid_selector( mut client: ink_e2e::Client, @@ -184,8 +243,7 @@ mod call_builder { .call(&ink_e2e::dave(), call, 0, None) .await .expect("Client failed to call `call_builder::call_instantiate`.") - .return_value() - .expect("Dispatching `call_builder::call_instantiate` failed."); + .return_value(); assert!( call_result.is_some(), @@ -221,8 +279,7 @@ mod call_builder { .call(&ink_e2e::eve(), call, 0, None) .await .expect("Client failed to call `call_builder::call_instantiate`.") - .return_value() - .expect("Dispatching `call_builder::call_instantiate` failed."); + .return_value(); assert!( call_result.is_none(), diff --git a/examples/lang-err-integration-tests/constructors-return-value/lib.rs b/examples/lang-err-integration-tests/constructors-return-value/lib.rs index 53147d9d41f..35716615f18 100644 --- a/examples/lang-err-integration-tests/constructors-return-value/lib.rs +++ b/examples/lang-err-integration-tests/constructors-return-value/lib.rs @@ -191,8 +191,7 @@ pub mod constructors_return_value { .call(&ink_e2e::bob(), get, 0, None) .await .expect("Calling `get_value` failed") - .return_value() - .expect("Input is valid, call must not fail."); + .return_value(); assert_eq!( true, value, diff --git a/examples/lang-err-integration-tests/contract-ref/lib.rs b/examples/lang-err-integration-tests/contract-ref/lib.rs index 9ab9ec45ab3..64074d14faa 100755 --- a/examples/lang-err-integration-tests/contract-ref/lib.rs +++ b/examples/lang-err-integration-tests/contract-ref/lib.rs @@ -80,9 +80,7 @@ mod contract_ref { .call(&ink_e2e::alice(), get_check, 0, None) .await .expect("Calling `get_check` failed"); - let initial_value = get_call_result - .return_value() - .expect("Input is valid, call must not fail."); + let initial_value = get_call_result.return_value(); let flip_check = build_message::(contract_acc_id.clone()) .call(|contract| contract.flip_check()); @@ -101,9 +99,7 @@ mod contract_ref { .call(&ink_e2e::alice(), get_check, 0, None) .await .expect("Calling `get_check` failed"); - let flipped_value = get_call_result - .return_value() - .expect("Input is valid, call must not fail."); + let flipped_value = get_call_result.return_value(); assert!(flipped_value != initial_value); Ok(()) diff --git a/examples/lang-err-integration-tests/integration-flipper/lib.rs b/examples/lang-err-integration-tests/integration-flipper/lib.rs index c000ad24802..0df61977285 100644 --- a/examples/lang-err-integration-tests/integration-flipper/lib.rs +++ b/examples/lang-err-integration-tests/integration-flipper/lib.rs @@ -77,9 +77,7 @@ pub mod integration_flipper { .call(&ink_e2e::alice(), get, 0, None) .await .expect("Calling `get` failed"); - let initial_value = get_call_result - .return_value() - .expect("Input is valid, call must not fail."); + let initial_value = get_call_result.return_value(); let flip = build_message::(contract_acc_id) .call(|contract| contract.flip()); @@ -98,9 +96,7 @@ pub mod integration_flipper { .call(&ink_e2e::alice(), get, 0, None) .await .expect("Calling `get` failed"); - let flipped_value = get_call_result - .return_value() - .expect("Input is valid, call must not fail."); + let flipped_value = get_call_result.return_value(); assert!(flipped_value != initial_value); Ok(()) @@ -123,9 +119,7 @@ pub mod integration_flipper { .call(&ink_e2e::bob(), get, 0, None) .await .expect("Calling `get` failed"); - let initial_value = get_call_result - .return_value() - .expect("Input is valid, call must not fail."); + let initial_value = get_call_result.return_value(); let err_flip = build_message::(contract_acc_id) .call(|contract| contract.err_flip()); @@ -143,9 +137,7 @@ pub mod integration_flipper { .call(&ink_e2e::bob(), get, 0, None) .await .expect("Calling `get` failed"); - let flipped_value = get_call_result - .return_value() - .expect("Input is valid, call must not fail."); + let flipped_value = get_call_result.return_value(); assert!(flipped_value == initial_value); Ok(())