diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 065d4112978..b5d351448de 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -21,7 +21,6 @@ use crate::{ TypedEnvBackend, }, call::{ - utils::ReturnType, CallParams, CreateParams, }, @@ -216,33 +215,7 @@ pub fn clear_contract_storage(key: &Key) { }) } -/// Invokes a contract message. -/// -/// # Note -/// -/// - Prefer using this over [`eval_contract`] if possible. [`invoke_contract`] -/// will generally have a better performance since it won't try to fetch any results. -/// - This is a low level way to invoke another smart contract. -/// Prefer to use the ink! guided and type safe approach to using this. -/// -/// # Errors -/// -/// - If the called account does not exist. -/// - If the called account is not a contract. -/// - If arguments passed to the called contract message are invalid. -/// - If the called contract execution has trapped. -/// - If the called contract ran out of gas upon execution. -pub fn invoke_contract(params: &CallParams) -> Result<()> -where - T: Environment, - Args: scale::Encode, -{ - ::on_instance(|instance| { - TypedEnvBackend::invoke_contract::(instance, params) - }) -} - -/// Evaluates a contract message and returns its result. +/// Invokes a contract message and returns its result. /// /// # Note /// @@ -257,14 +230,14 @@ 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 eval_contract(params: &CallParams>) -> Result +pub fn invoke_contract(params: &CallParams) -> Result where T: Environment, Args: scale::Encode, R: scale::Decode, { ::on_instance(|instance| { - TypedEnvBackend::eval_contract::(instance, params) + TypedEnvBackend::invoke_contract::(instance, params) }) } diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 7182d6ad9a8..5fed490a2c9 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -14,7 +14,6 @@ use crate::{ call::{ - utils::ReturnType, CallParams, CreateParams, }, @@ -359,27 +358,14 @@ pub trait TypedEnvBackend: EnvBackend { T: Environment, Event: Topics + scale::Encode; - /// Invokes a contract message. + /// Invokes a contract message and returns its result. /// /// # Note /// /// For more details visit: [`invoke_contract`][`crate::invoke_contract`] - fn invoke_contract( + fn invoke_contract( &mut self, - call_data: &CallParams, - ) -> Result<()> - where - T: Environment, - Args: scale::Encode; - - /// Evaluates a contract message and returns its result. - /// - /// # Note - /// - /// For more details visit: [`eval_contract`][`crate::eval_contract`] - fn eval_contract( - &mut self, - call_data: &CallParams>, + call_data: &CallParams, ) -> Result where T: Environment, diff --git a/crates/env/src/call/call_builder.rs b/crates/env/src/call/call_builder.rs index b7a37a1177e..3bef7651301 100644 --- a/crates/env/src/call/call_builder.rs +++ b/crates/env/src/call/call_builder.rs @@ -84,38 +84,17 @@ where } } -impl CallParams -where - E: Environment, - Args: scale::Encode, -{ - /// Invokes the contract with the given built-up call parameters. - /// - /// # Note - /// - /// Prefer [`invoke`](`Self::invoke`) over [`eval`](`Self::eval`) if the - /// called contract message does not return anything because it is more efficient. - pub fn invoke(&self) -> Result<(), crate::Error> { - crate::invoke_contract(self) - } -} - -impl CallParams> +impl CallParams where E: Environment, Args: scale::Encode, R: scale::Decode, { - /// Evaluates the contract with the given built-up call parameters. + /// Invokes the contract with the given built-up call parameters. /// /// Returns the result of the contract execution. - /// - /// # Note - /// - /// Prefer [`invoke`](`Self::invoke`) over [`eval`](`Self::eval`) if the - /// called contract message does not return anything because it is more efficient. - pub fn eval(&self) -> Result { - crate::eval_contract(self) + pub fn invoke(&self) -> Result { + crate::invoke_contract(self) } } @@ -179,7 +158,7 @@ where /// # use ::ink_env::{ /// # Environment, /// # DefaultEnvironment, -/// # call::{build_call, Selector, ExecutionInput, utils::ReturnType}, +/// # call::{build_call, Selector, ExecutionInput}, /// # }; /// # type AccountId = ::AccountId; /// let my_return_value: i32 = build_call::() @@ -192,7 +171,7 @@ where /// .push_arg(true) /// .push_arg(&[0x10; 32]) /// ) -/// .returns::>() +/// .returns::() /// .fire() /// .unwrap(); /// ``` @@ -328,18 +307,6 @@ where } } -mod seal { - /// Used to prevent users from implementing `IndicateReturnType` for their own types. - pub trait Sealed {} - impl Sealed for () {} - impl Sealed for super::ReturnType {} -} - -/// Types that can be used in [`CallBuilder::returns`] to signal return type. -pub trait IndicateReturnType: Default + self::seal::Sealed {} -impl IndicateReturnType for () {} -impl IndicateReturnType for ReturnType {} - impl CallBuilder>> where @@ -350,14 +317,11 @@ where /// # Note /// /// Either use `.returns::<()>` to signal that the call does not return a value - /// or use `.returns::>` to signal that the call returns a value of - /// type `T`. + /// or use `.returns::` to signal that the call returns a value of type `T`. #[inline] pub fn returns( self, - ) -> CallBuilder> - where - R: IndicateReturnType, + ) -> CallBuilder>> { CallBuilder { env: Default::default(), @@ -414,7 +378,7 @@ impl GasLimit, TransferredValue, Set>, - Set, + Set>, > where E: Environment, @@ -465,27 +429,6 @@ where } } -impl - CallBuilder< - E, - Set, - GasLimit, - TransferredValue, - Set>, - Set<()>, - > -where - E: Environment, - GasLimit: Unwrap, - Args: scale::Encode, - TransferredValue: Unwrap, -{ - /// Invokes the cross-chain function call. - pub fn fire(self) -> Result<(), Error> { - self.params().invoke() - } -} - impl CallBuilder< E, @@ -524,6 +467,6 @@ where { /// Invokes the cross-chain function call and returns the result. pub fn fire(self) -> Result { - self.params().eval() + self.params().invoke() } } diff --git a/crates/env/src/call/common.rs b/crates/env/src/call/common.rs index 94cf6c7bfcb..e1cc4171a2d 100644 --- a/crates/env/src/call/common.rs +++ b/crates/env/src/call/common.rs @@ -18,7 +18,7 @@ use core::marker::PhantomData; /// Represents a return type. /// -/// Used as a marker type to differentiate at compile-time between invoke and evaluate. +/// Used as a marker type to define the return type of an ink! message in call builders. #[derive(Debug)] pub struct ReturnType(PhantomData T>); diff --git a/crates/env/src/call/mod.rs b/crates/env/src/call/mod.rs index 7cb8c4fa97c..a4c6fa653f8 100644 --- a/crates/env/src/call/mod.rs +++ b/crates/env/src/call/mod.rs @@ -23,7 +23,6 @@ mod selector; /// Utility types for the cross-contract calling API. pub mod utils { pub use super::{ - call_builder::IndicateReturnType, common::{ ReturnType, Set, diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 2ecf10a0acd..d8a98edb6a5 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -15,7 +15,6 @@ use super::EnvInstance; use crate::{ call::{ - utils::ReturnType, CallParams, CreateParams, }, @@ -387,10 +386,14 @@ impl TypedEnvBackend for EnvInstance { self.engine.deposit_event(&enc_topics[..], enc_data); } - fn invoke_contract(&mut self, params: &CallParams) -> Result<()> + fn invoke_contract( + &mut self, + params: &CallParams, + ) -> Result where T: Environment, Args: scale::Encode, + R: scale::Decode, { let _gas_limit = params.gas_limit(); let _callee = params.callee(); @@ -400,18 +403,6 @@ impl TypedEnvBackend for EnvInstance { unimplemented!("off-chain environment does not support contract invocation") } - fn eval_contract( - &mut self, - _call_params: &CallParams>, - ) -> Result - where - T: Environment, - Args: scale::Encode, - R: scale::Decode, - { - unimplemented!("off-chain environment does not support contract evaluation") - } - fn instantiate_contract( &mut self, params: &CreateParams, diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 4ee4b5e0864..548bf0dab7e 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -20,7 +20,6 @@ use super::{ }; use crate::{ call::{ - utils::ReturnType, CallParams, CreateParams, }, @@ -215,45 +214,6 @@ impl EnvInstance { ext_fn(full_scope); scale::Decode::decode(&mut &full_scope[..]).map_err(Into::into) } - - /// Reusable implementation for invoking another contract message. - fn invoke_contract_impl( - &mut self, - params: &CallParams, - ) -> Result - where - T: Environment, - Args: scale::Encode, - R: scale::Decode, - { - let mut scope = self.scoped_buffer(); - let gas_limit = params.gas_limit(); - let enc_callee = scope.take_encoded(params.callee()); - let enc_transferred_value = scope.take_encoded(params.transferred_value()); - let call_flags = params.call_flags(); - let enc_input = if !call_flags.forward_input() && !call_flags.clone_input() { - scope.take_encoded(params.exec_input()) - } else { - &mut [] - }; - let output = &mut scope.take_rest(); - let flags = params.call_flags().into_u32(); - let call_result = ext::call( - flags, - enc_callee, - gas_limit, - enc_transferred_value, - enc_input, - output, - ); - match call_result { - Ok(()) | Err(ext::Error::CalleeReverted) => { - let decoded = scale::Decode::decode(&mut &output[..])?; - Ok(decoded) - } - Err(actual_error) => Err(actual_error.into()), - } - } } impl EnvBackend for EnvInstance { @@ -396,27 +356,42 @@ impl TypedEnvBackend for EnvInstance { ext::deposit_event(enc_topics, enc_data); } - fn invoke_contract( + fn invoke_contract( &mut self, - call_params: &CallParams, - ) -> Result<()> - where - T: Environment, - Args: scale::Encode, - { - self.invoke_contract_impl(call_params) - } - - fn eval_contract( - &mut self, - call_params: &CallParams>, + params: &CallParams, ) -> Result where T: Environment, Args: scale::Encode, R: scale::Decode, { - self.invoke_contract_impl(call_params) + let mut scope = self.scoped_buffer(); + let gas_limit = params.gas_limit(); + let enc_callee = scope.take_encoded(params.callee()); + let enc_transferred_value = scope.take_encoded(params.transferred_value()); + let call_flags = params.call_flags(); + let enc_input = if !call_flags.forward_input() && !call_flags.clone_input() { + scope.take_encoded(params.exec_input()) + } else { + &mut [] + }; + let output = &mut scope.take_rest(); + let flags = params.call_flags().into_u32(); + let call_result = ext::call( + flags, + enc_callee, + gas_limit, + enc_transferred_value, + enc_input, + output, + ); + match call_result { + Ok(()) | Err(ext::Error::CalleeReverted) => { + let decoded = scale::Decode::decode(&mut &output[..])?; + Ok(decoded) + } + Err(actual_error) => Err(actual_error.into()), + } } fn instantiate_contract( diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 57750e47a84..757d15ae2f5 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -372,10 +372,8 @@ impl CallBuilder<'_> { let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let mut_tok = callable.receiver().is_ref_mut().then(|| quote! { mut }); let output = message.output(); - let output_sig = output.map_or_else( - || quote! { () }, - |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, - ); + let return_type = + output.map_or_else(|| quote! { () }, |output| quote! { #output }); let output_span = output.span(); let output_type = quote_spanned!(output_span=> ::ink_env::call::CallBuilder< @@ -384,7 +382,7 @@ impl CallBuilder<'_> { ::ink_env::call::utils::Unset< ::core::primitive::u64 >, ::ink_env::call::utils::Unset< ::Balance >, ::ink_env::call::utils::Set< ::ink_env::call::ExecutionInput<#arg_list> >, - ::ink_env::call::utils::Set<#output_sig>, + ::ink_env::call::utils::Set< ::ink_env::call::utils::ReturnType<#return_type> >, > ); quote_spanned!(span=> @@ -405,7 +403,7 @@ impl CallBuilder<'_> { .push_arg(#input_bindings) )* ) - .returns::<#output_sig>() + .returns::<#return_type>() } ) } diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 3f820c98095..21414335e8b 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -365,10 +365,8 @@ impl CallBuilder<'_> { .filter_attr(message.attrs()); let output_ident = generator::output_ident(message_ident); let output = message.output(); - let output_sig = output.map_or_else( - || quote! { () }, - |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, - ); + let output_type = + output.map_or_else(|| quote! { () }, |output| quote! { #output }); let selector_bytes = selector.hex_lits(); let input_bindings = generator::input_bindings(message.inputs()); let input_types = generator::input_types(message.inputs()); @@ -382,7 +380,7 @@ impl CallBuilder<'_> { ::ink_env::call::utils::Unset< ::core::primitive::u64 >, ::ink_env::call::utils::Unset< ::Balance >, ::ink_env::call::utils::Set< ::ink_env::call::ExecutionInput<#arg_list> >, - ::ink_env::call::utils::Set<#output_sig>, + ::ink_env::call::utils::Set< ::ink_env::call::utils::ReturnType<#output_type> >, >; #( #attrs )* @@ -401,7 +399,7 @@ impl CallBuilder<'_> { .push_arg(#input_bindings) )* ) - .returns::<#output_sig>() + .returns::<#output_type>() } ) } diff --git a/crates/lang/src/env_access.rs b/crates/lang/src/env_access.rs index 11ca46d40ef..572a529795a 100644 --- a/crates/lang/src/env_access.rs +++ b/crates/lang/src/env_access.rs @@ -16,7 +16,6 @@ use crate::ChainExtensionInstance; use core::marker::PhantomData; use ink_env::{ call::{ - utils::ReturnType, CallParams, CreateParams, }, @@ -504,7 +503,7 @@ where ink_env::instantiate_contract::(params) } - /// Invokes a contract message without fetching its result. + /// Invokes a contract message and returns its result. /// /// # Example /// @@ -527,9 +526,9 @@ where /// # Self {} /// # } /// # - /// /// Invokes another contract message without fetching the result. + /// /// Invokes a contract message and fetches the result. /// #[ink(message)] - /// pub fn invoke_contract(&self) { + /// pub fn invoke_contract(&self) -> i32 { /// let call_params = build_call::() /// .callee(AccountId::from([0x42; 32])) /// .gas_limit(5000) @@ -540,9 +539,9 @@ where /// .push_arg(true) /// .push_arg(&[0x10u8; 32]) /// ) - /// .returns::<()>() + /// .returns::() /// .params(); - /// self.env().invoke_contract(&call_params).expect("call invocation must succeed"); + /// self.env().invoke_contract(&call_params).expect("call invocation must succeed") /// } /// # /// # } @@ -552,70 +551,12 @@ where /// # Note /// /// For more details visit: [`ink_env::invoke_contract`] - pub fn invoke_contract(self, params: &CallParams) -> Result<()> - where - Args: scale::Encode, - { - ink_env::invoke_contract::(params) - } - - /// Evaluates a contract message and returns its result. - /// - /// # Example - /// - /// ``` - /// # use ink_lang as ink; - /// # #[ink::contract] - /// # pub mod my_contract { - /// use ink_env::{ - /// DefaultEnvironment, - /// call::{build_call, Selector, ExecutionInput, utils::ReturnType} - /// }; - /// - /// # - /// # #[ink(storage)] - /// # pub struct MyContract { } - /// # - /// # impl MyContract { - /// # #[ink(constructor)] - /// # pub fn new() -> Self { - /// # Self {} - /// # } - /// # - /// /// Evaluates a contract message and fetches the result. - /// #[ink(message)] - /// pub fn evaluate_contract(&self) -> i32 { - /// let call_params = build_call::() - /// .callee(AccountId::from([0x42; 32])) - /// .gas_limit(5000) - /// .transferred_value(10) - /// .exec_input( - /// ExecutionInput::new(Selector::new([0xCA, 0xFE, 0xBA, 0xBE])) - /// .push_arg(42) - /// .push_arg(true) - /// .push_arg(&[0x10u8; 32]) - /// ) - /// .returns::>() - /// .params(); - /// self.env().eval_contract(&call_params).expect("call invocation must succeed") - /// } - /// # - /// # } - /// # } - /// ``` - /// - /// # Note - /// - /// For more details visit: [`ink_env::eval_contract`] - pub fn eval_contract( - self, - params: &CallParams>, - ) -> Result + pub fn invoke_contract(self, params: &CallParams) -> Result where Args: scale::Encode, R: scale::Decode, { - ink_env::eval_contract::(params) + ink_env::invoke_contract::(params) } /// Terminates the existence of a contract. diff --git a/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr index 9299baed8f3..853f789bf6d 100644 --- a/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr +++ b/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr @@ -32,11 +32,11 @@ note: required by a bound in `ExecutionInput::>::push_arg` -error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>`, but its trait bounds were not satisfied +error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set>>`, but its trait bounds were not satisfied --> tests/ui/contract/fail/message-input-non-codec.rs:18:9 | 18 | pub fn message(&self, _input: NonCodecType) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>` due to unsatisfied trait bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set>>` due to unsatisfied trait bounds | ::: $WORKSPACE/crates/env/src/call/execution_input.rs | diff --git a/crates/lang/tests/ui/trait_def/fail/message_input_non_codec.stderr b/crates/lang/tests/ui/trait_def/fail/message_input_non_codec.stderr index 2b0fe21ef79..75e38274408 100644 --- a/crates/lang/tests/ui/trait_def/fail/message_input_non_codec.stderr +++ b/crates/lang/tests/ui/trait_def/fail/message_input_non_codec.stderr @@ -25,12 +25,12 @@ note: required by a bound in `ExecutionInput::>::push_arg` -error[E0599]: the method `fire` exists for struct `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set, ArgumentList>>>, Set<()>>`, but its trait bounds were not satisfied +error[E0599]: the method `fire` exists for struct `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set, ArgumentList>>>, Set>>`, but its trait bounds were not satisfied --> tests/ui/trait_def/fail/message_input_non_codec.rs:7:5 | 7 | / #[ink(message)] 8 | | fn message(&self, input: NonCodec); - | |_______________________________________^ method cannot be called on `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set, ArgumentList>>>, Set<()>>` due to unsatisfied trait bounds + | |_______________________________________^ method cannot be called on `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set, ArgumentList>>>, Set>>` due to unsatisfied trait bounds | ::: $WORKSPACE/crates/env/src/call/execution_input.rs | diff --git a/examples/erc1155/lib.rs b/examples/erc1155/lib.rs index 60a643eb32f..7060f57e9e5 100644 --- a/examples/erc1155/lib.rs +++ b/examples/erc1155/lib.rs @@ -381,13 +381,12 @@ mod erc1155 { value: Balance, data: Vec, ) { - // This is disabled during tests due to the use of `eval_contract()` not being + // This is disabled during tests due to the use of `invoke_contract()` not being // supported (tests end up panicking). #[cfg(not(test))] { use ink_env::call::{ build_call, - utils::ReturnType, ExecutionInput, Selector, }; @@ -405,10 +404,10 @@ mod erc1155 { .push_arg(value) .push_arg(data), ) - .returns::>>() + .returns::>() .params(); - match ink_env::eval_contract(¶ms) { + match ink_env::invoke_contract(¶ms) { Ok(v) => { ink_env::debug_println!( "Received return value \"{:?}\" from contract {:?}", diff --git a/examples/multisig/lib.rs b/examples/multisig/lib.rs index 365834cc30c..e6e643e8d9b 100755 --- a/examples/multisig/lib.rs +++ b/examples/multisig/lib.rs @@ -66,7 +66,6 @@ use ink_lang as ink; mod multisig { use ink_env::call::{ build_call, - utils::ReturnType, ExecutionInput, }; use ink_prelude::vec::Vec; @@ -551,7 +550,7 @@ mod multisig { .exec_input( ExecutionInput::new(t.selector.into()).push_arg(CallInput(&t.input)), ) - .returns::>>() + .returns::>() .fire() .map_err(|_| Error::TransactionFailed); self.env().emit_event(Execution {